current-data-py 0.1.2__tar.gz → 0.1.5__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.
- current_data_py-0.1.5/MANIFEST.in +4 -0
- current_data_py-0.1.5/PKG-INFO +98 -0
- current_data_py-0.1.5/README.md +87 -0
- {current_data_py-0.1.2 → current_data_py-0.1.5}/__init__.py +8 -6
- current_data_py-0.1.5/current_data_py.egg-info/PKG-INFO +98 -0
- {current_data_py-0.1.2 → current_data_py-0.1.5}/current_data_py.egg-info/SOURCES.txt +6 -0
- {current_data_py-0.1.2 → current_data_py-0.1.5}/current_data_py.egg-info/requires.txt +0 -2
- {current_data_py-0.1.2 → current_data_py-0.1.5}/examples/__init__.py +1 -1
- {current_data_py-0.1.2 → current_data_py-0.1.5}/examples/list_schemas.py +7 -7
- {current_data_py-0.1.2 → current_data_py-0.1.5}/examples/read_remote_td.py +54 -48
- {current_data_py-0.1.2 → current_data_py-0.1.5}/examples/read_td.py +30 -30
- {current_data_py-0.1.2 → current_data_py-0.1.5}/examples/write_td.py +30 -30
- current_data_py-0.1.5/management.py +114 -0
- current_data_py-0.1.5/oss.py +182 -0
- current_data_py-0.1.5/proto_gen/python/management/metadata/metadata_pb2.py +62 -0
- current_data_py-0.1.5/proto_gen/python/management/service/service_pb2.py +64 -0
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/management/service/service_pb2_grpc.py +330 -330
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/builtin_interfaces/duration_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/builtin_interfaces/time_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/custom_msgs/joint_current_pb2.py +26 -26
- current_data_py-0.1.5/proto_gen/python/msg/custom_msgs/slam_quality_pb2.py +25 -0
- current_data_py-0.1.5/proto_gen/python/msg/custom_msgs/sonic_frame_pb2.py +25 -0
- current_data_py-0.1.5/proto_gen/python/msg/custom_msgs/target_quality_pb2.py +25 -0
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/foxglove/compressed_audio_pb2.py +26 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/foxglove/compressed_video_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/point32_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/point_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/pose_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/pose_stamped_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/pose_with_covariance_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/pose_with_covariance_stamped_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/quaternion_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/transform_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/transform_stamped_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/twist_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/twist_stamped_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/twist_with_covariance_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/twist_with_covariance_stamped_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/vector3_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/wrench_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/geometry_msgs/wrench_stamped_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/nav_msgs/map_meta_data_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/nav_msgs/occupancy_grid_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/nav_msgs/odometry_pb2.py +28 -28
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/nav_msgs/path_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/battery_state_pb2.py +32 -32
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/camera_info_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/compressed_image_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/image_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/imu_pb2.py +28 -28
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/joint_state_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/laser_scan_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/nav_sat_fix_pb2.py +29 -29
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/nav_sat_status_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/point_cloud2_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/point_field_pb2.py +27 -27
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/range_pb2.py +28 -28
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/sensor_msgs/region_of_interest_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/std_msgs/bool_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/std_msgs/color_rgba_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/std_msgs/float32_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/std_msgs/float64_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/std_msgs/header_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/std_msgs/int32_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/std_msgs/string_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/std_msgs/uint32_pb2.py +25 -25
- {current_data_py-0.1.2 → current_data_py-0.1.5}/proto_gen/python/msg/tf2_msgs/tf_message_pb2.py +26 -26
- {current_data_py-0.1.2 → current_data_py-0.1.5}/pyproject.toml +21 -19
- {current_data_py-0.1.2 → current_data_py-0.1.5}/remote/__init__.py +7 -7
- {current_data_py-0.1.2 → current_data_py-0.1.5}/remote/client.py +61 -85
- {current_data_py-0.1.2 → current_data_py-0.1.5}/remote/source.py +98 -97
- {current_data_py-0.1.2 → current_data_py-0.1.5}/schema/__init__.py +105 -99
- {current_data_py-0.1.2 → current_data_py-0.1.5}/schema/message_metadata.py +30 -30
- {current_data_py-0.1.2 → current_data_py-0.1.5}/setup.py +60 -60
- current_data_py-0.1.5/tests/check_management.py +253 -0
- current_data_py-0.1.5/tests/check_oss.py +317 -0
- {current_data_py-0.1.2 → current_data_py-0.1.5}/tests/check_package.py +43 -43
- {current_data_py-0.1.2 → current_data_py-0.1.5}/tests/check_remote.py +231 -172
- current_data_py-0.1.2/MANIFEST.in +0 -2
- current_data_py-0.1.2/PKG-INFO +0 -154
- current_data_py-0.1.2/README.md +0 -142
- current_data_py-0.1.2/current_data_py.egg-info/PKG-INFO +0 -154
- current_data_py-0.1.2/proto_gen/python/management/metadata/metadata_pb2.py +0 -38
- current_data_py-0.1.2/proto_gen/python/management/service/service_pb2.py +0 -64
- {current_data_py-0.1.2 → current_data_py-0.1.5}/current_data_py.egg-info/dependency_links.txt +0 -0
- {current_data_py-0.1.2 → current_data_py-0.1.5}/current_data_py.egg-info/top_level.txt +0 -0
- {current_data_py-0.1.2 → current_data_py-0.1.5}/setup.cfg +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: current-data-py
|
|
3
|
+
Version: 0.1.5
|
|
4
|
+
Summary: Current Data protobuf messages and schema metadata
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: protobuf>=3.20
|
|
8
|
+
Requires-Dist: turbodata==0.1.0
|
|
9
|
+
Requires-Dist: grpcio>=1.51.1
|
|
10
|
+
Requires-Dist: alibabacloud-oss-v2<2,>=1.4.0
|
|
11
|
+
|
|
12
|
+
# current-data-py
|
|
13
|
+
|
|
14
|
+
## Management
|
|
15
|
+
|
|
16
|
+
`ManagementClient()` connects to `data.current-robotics.work:443` over TLS.
|
|
17
|
+
Pass `address="host:443"` to override it, or supply your own gRPC channel.
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from current_data_py.management import ManagementClient, Metadata, MetadataFilter
|
|
21
|
+
|
|
22
|
+
with ManagementClient() as client:
|
|
23
|
+
upload = client.get_upload_credentials(data_type="CURRENT_V2")
|
|
24
|
+
read = client.get_read_credentials(bucket="data-infra-raw-data")
|
|
25
|
+
|
|
26
|
+
# Register an already uploaded file; replace the example file details.
|
|
27
|
+
record = client.register_data(Metadata(
|
|
28
|
+
name="recording",
|
|
29
|
+
data_type="DATA_TYPE_CURRENT_V2",
|
|
30
|
+
storages=[{"bucket": "data-infra-202607", "object_key": "raw_converted/recording.td"}],
|
|
31
|
+
file_info={"size_bytes": 1234, "checksum": "sha256:<file-hash>"},
|
|
32
|
+
))
|
|
33
|
+
for item in client.stream_data_references(MetadataFilter(name_prefix="recording")):
|
|
34
|
+
print(item.id, item.storages)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`Metadata`, `MetadataFilter`, and responses are Protobuf objects exported by the
|
|
38
|
+
SDK. Registration only saves metadata; it does not upload files. Credential
|
|
39
|
+
calls return fresh credentials without caching. Calls accept `timeout=` and
|
|
40
|
+
`metadata=` for gRPC headers.
|
|
41
|
+
|
|
42
|
+
## OSS
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from current_data_py.management import ManagementClient
|
|
46
|
+
from current_data_py.oss import OSSClient
|
|
47
|
+
|
|
48
|
+
with ManagementClient() as management:
|
|
49
|
+
with OSSClient(management, permission="read", bucket="data-infra-raw-data") as source:
|
|
50
|
+
source.download_file("collections/recording/input.h5", "/tmp/input.h5")
|
|
51
|
+
|
|
52
|
+
# Convert the input into /tmp/output.td before uploading.
|
|
53
|
+
with OSSClient(management, permission="upload", data_type="CURRENT_V2") as destination:
|
|
54
|
+
key = destination.object_prefix + "recording/output.td"
|
|
55
|
+
destination.upload_file(key, "/tmp/output.td")
|
|
56
|
+
print(destination.bucket, key) # Use these values when registering metadata.
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- Read access covers the requested bucket, subject to server permissions.
|
|
60
|
+
Uploads default to `data_type="RAW"`; the server chooses the bucket and prefix.
|
|
61
|
+
- Credentials refresh automatically. Expired tokens trigger one refresh and retry.
|
|
62
|
+
- Uploads reject overwrites by default; set `forbid_overwrite=False` to replace.
|
|
63
|
+
Downloads replace the local file only on success; its parent directory must exist.
|
|
64
|
+
- Uploads use a single PutObject request ([maximum 5 GiB](https://www.alibabacloud.com/help/en/oss/developer-reference/upload-files-using-oss-sdk-for-python-v2/)); multipart upload is not supported.
|
|
65
|
+
- Supply `region=` for custom upload endpoints. Deploy the current management
|
|
66
|
+
credential API before using the new bucket and data-type arguments.
|
|
67
|
+
|
|
68
|
+
## 打包
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cd current_data_py # 从仓库根目录执行
|
|
72
|
+
# 发布新版本前,更新 pyproject.toml 中的 version
|
|
73
|
+
python -m pip install build twine
|
|
74
|
+
rm -rf build dist
|
|
75
|
+
python -m build
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 测试
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
python -m twine check dist/*
|
|
82
|
+
python tests/check_distribution.py
|
|
83
|
+
python -m pip install --force-reinstall dist/*.whl
|
|
84
|
+
python -I tests/check_package.py
|
|
85
|
+
python -I tests/check_management.py
|
|
86
|
+
python -I tests/check_remote.py
|
|
87
|
+
python -I tests/check_oss.py
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 推送
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# TestPyPI
|
|
94
|
+
python -m twine upload --repository testpypi dist/*
|
|
95
|
+
|
|
96
|
+
# PyPI
|
|
97
|
+
python -m twine upload dist/*
|
|
98
|
+
```
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# current-data-py
|
|
2
|
+
|
|
3
|
+
## Management
|
|
4
|
+
|
|
5
|
+
`ManagementClient()` connects to `data.current-robotics.work:443` over TLS.
|
|
6
|
+
Pass `address="host:443"` to override it, or supply your own gRPC channel.
|
|
7
|
+
|
|
8
|
+
```python
|
|
9
|
+
from current_data_py.management import ManagementClient, Metadata, MetadataFilter
|
|
10
|
+
|
|
11
|
+
with ManagementClient() as client:
|
|
12
|
+
upload = client.get_upload_credentials(data_type="CURRENT_V2")
|
|
13
|
+
read = client.get_read_credentials(bucket="data-infra-raw-data")
|
|
14
|
+
|
|
15
|
+
# Register an already uploaded file; replace the example file details.
|
|
16
|
+
record = client.register_data(Metadata(
|
|
17
|
+
name="recording",
|
|
18
|
+
data_type="DATA_TYPE_CURRENT_V2",
|
|
19
|
+
storages=[{"bucket": "data-infra-202607", "object_key": "raw_converted/recording.td"}],
|
|
20
|
+
file_info={"size_bytes": 1234, "checksum": "sha256:<file-hash>"},
|
|
21
|
+
))
|
|
22
|
+
for item in client.stream_data_references(MetadataFilter(name_prefix="recording")):
|
|
23
|
+
print(item.id, item.storages)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`Metadata`, `MetadataFilter`, and responses are Protobuf objects exported by the
|
|
27
|
+
SDK. Registration only saves metadata; it does not upload files. Credential
|
|
28
|
+
calls return fresh credentials without caching. Calls accept `timeout=` and
|
|
29
|
+
`metadata=` for gRPC headers.
|
|
30
|
+
|
|
31
|
+
## OSS
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from current_data_py.management import ManagementClient
|
|
35
|
+
from current_data_py.oss import OSSClient
|
|
36
|
+
|
|
37
|
+
with ManagementClient() as management:
|
|
38
|
+
with OSSClient(management, permission="read", bucket="data-infra-raw-data") as source:
|
|
39
|
+
source.download_file("collections/recording/input.h5", "/tmp/input.h5")
|
|
40
|
+
|
|
41
|
+
# Convert the input into /tmp/output.td before uploading.
|
|
42
|
+
with OSSClient(management, permission="upload", data_type="CURRENT_V2") as destination:
|
|
43
|
+
key = destination.object_prefix + "recording/output.td"
|
|
44
|
+
destination.upload_file(key, "/tmp/output.td")
|
|
45
|
+
print(destination.bucket, key) # Use these values when registering metadata.
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- Read access covers the requested bucket, subject to server permissions.
|
|
49
|
+
Uploads default to `data_type="RAW"`; the server chooses the bucket and prefix.
|
|
50
|
+
- Credentials refresh automatically. Expired tokens trigger one refresh and retry.
|
|
51
|
+
- Uploads reject overwrites by default; set `forbid_overwrite=False` to replace.
|
|
52
|
+
Downloads replace the local file only on success; its parent directory must exist.
|
|
53
|
+
- Uploads use a single PutObject request ([maximum 5 GiB](https://www.alibabacloud.com/help/en/oss/developer-reference/upload-files-using-oss-sdk-for-python-v2/)); multipart upload is not supported.
|
|
54
|
+
- Supply `region=` for custom upload endpoints. Deploy the current management
|
|
55
|
+
credential API before using the new bucket and data-type arguments.
|
|
56
|
+
|
|
57
|
+
## 打包
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cd current_data_py # 从仓库根目录执行
|
|
61
|
+
# 发布新版本前,更新 pyproject.toml 中的 version
|
|
62
|
+
python -m pip install build twine
|
|
63
|
+
rm -rf build dist
|
|
64
|
+
python -m build
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 测试
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python -m twine check dist/*
|
|
71
|
+
python tests/check_distribution.py
|
|
72
|
+
python -m pip install --force-reinstall dist/*.whl
|
|
73
|
+
python -I tests/check_package.py
|
|
74
|
+
python -I tests/check_management.py
|
|
75
|
+
python -I tests/check_remote.py
|
|
76
|
+
python -I tests/check_oss.py
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 推送
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# TestPyPI
|
|
83
|
+
python -m twine upload --repository testpypi dist/*
|
|
84
|
+
|
|
85
|
+
# PyPI
|
|
86
|
+
python -m twine upload dist/*
|
|
87
|
+
```
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
"""Protobuf message schemas and metadata for Current Data."""
|
|
2
|
-
|
|
3
|
-
from .schema.message_metadata import descriptor_set, topic_metadata
|
|
4
|
-
from .schema import SCHEMA_TO_CLASS
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
"""Protobuf message schemas and metadata for Current Data."""
|
|
2
|
+
|
|
3
|
+
from .schema.message_metadata import descriptor_set, topic_metadata
|
|
4
|
+
from .schema import SCHEMA_TO_CLASS
|
|
5
|
+
|
|
6
|
+
DEFAULT_ADDRESS = "data.current-robotics.work:443"
|
|
7
|
+
|
|
8
|
+
__all__ = ["DEFAULT_ADDRESS", "SCHEMA_TO_CLASS", "descriptor_set", "topic_metadata"]
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: current-data-py
|
|
3
|
+
Version: 0.1.5
|
|
4
|
+
Summary: Current Data protobuf messages and schema metadata
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: protobuf>=3.20
|
|
8
|
+
Requires-Dist: turbodata==0.1.0
|
|
9
|
+
Requires-Dist: grpcio>=1.51.1
|
|
10
|
+
Requires-Dist: alibabacloud-oss-v2<2,>=1.4.0
|
|
11
|
+
|
|
12
|
+
# current-data-py
|
|
13
|
+
|
|
14
|
+
## Management
|
|
15
|
+
|
|
16
|
+
`ManagementClient()` connects to `data.current-robotics.work:443` over TLS.
|
|
17
|
+
Pass `address="host:443"` to override it, or supply your own gRPC channel.
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from current_data_py.management import ManagementClient, Metadata, MetadataFilter
|
|
21
|
+
|
|
22
|
+
with ManagementClient() as client:
|
|
23
|
+
upload = client.get_upload_credentials(data_type="CURRENT_V2")
|
|
24
|
+
read = client.get_read_credentials(bucket="data-infra-raw-data")
|
|
25
|
+
|
|
26
|
+
# Register an already uploaded file; replace the example file details.
|
|
27
|
+
record = client.register_data(Metadata(
|
|
28
|
+
name="recording",
|
|
29
|
+
data_type="DATA_TYPE_CURRENT_V2",
|
|
30
|
+
storages=[{"bucket": "data-infra-202607", "object_key": "raw_converted/recording.td"}],
|
|
31
|
+
file_info={"size_bytes": 1234, "checksum": "sha256:<file-hash>"},
|
|
32
|
+
))
|
|
33
|
+
for item in client.stream_data_references(MetadataFilter(name_prefix="recording")):
|
|
34
|
+
print(item.id, item.storages)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`Metadata`, `MetadataFilter`, and responses are Protobuf objects exported by the
|
|
38
|
+
SDK. Registration only saves metadata; it does not upload files. Credential
|
|
39
|
+
calls return fresh credentials without caching. Calls accept `timeout=` and
|
|
40
|
+
`metadata=` for gRPC headers.
|
|
41
|
+
|
|
42
|
+
## OSS
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from current_data_py.management import ManagementClient
|
|
46
|
+
from current_data_py.oss import OSSClient
|
|
47
|
+
|
|
48
|
+
with ManagementClient() as management:
|
|
49
|
+
with OSSClient(management, permission="read", bucket="data-infra-raw-data") as source:
|
|
50
|
+
source.download_file("collections/recording/input.h5", "/tmp/input.h5")
|
|
51
|
+
|
|
52
|
+
# Convert the input into /tmp/output.td before uploading.
|
|
53
|
+
with OSSClient(management, permission="upload", data_type="CURRENT_V2") as destination:
|
|
54
|
+
key = destination.object_prefix + "recording/output.td"
|
|
55
|
+
destination.upload_file(key, "/tmp/output.td")
|
|
56
|
+
print(destination.bucket, key) # Use these values when registering metadata.
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- Read access covers the requested bucket, subject to server permissions.
|
|
60
|
+
Uploads default to `data_type="RAW"`; the server chooses the bucket and prefix.
|
|
61
|
+
- Credentials refresh automatically. Expired tokens trigger one refresh and retry.
|
|
62
|
+
- Uploads reject overwrites by default; set `forbid_overwrite=False` to replace.
|
|
63
|
+
Downloads replace the local file only on success; its parent directory must exist.
|
|
64
|
+
- Uploads use a single PutObject request ([maximum 5 GiB](https://www.alibabacloud.com/help/en/oss/developer-reference/upload-files-using-oss-sdk-for-python-v2/)); multipart upload is not supported.
|
|
65
|
+
- Supply `region=` for custom upload endpoints. Deploy the current management
|
|
66
|
+
credential API before using the new bucket and data-type arguments.
|
|
67
|
+
|
|
68
|
+
## 打包
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cd current_data_py # 从仓库根目录执行
|
|
72
|
+
# 发布新版本前,更新 pyproject.toml 中的 version
|
|
73
|
+
python -m pip install build twine
|
|
74
|
+
rm -rf build dist
|
|
75
|
+
python -m build
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 测试
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
python -m twine check dist/*
|
|
82
|
+
python tests/check_distribution.py
|
|
83
|
+
python -m pip install --force-reinstall dist/*.whl
|
|
84
|
+
python -I tests/check_package.py
|
|
85
|
+
python -I tests/check_management.py
|
|
86
|
+
python -I tests/check_remote.py
|
|
87
|
+
python -I tests/check_oss.py
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 推送
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# TestPyPI
|
|
94
|
+
python -m twine upload --repository testpypi dist/*
|
|
95
|
+
|
|
96
|
+
# PyPI
|
|
97
|
+
python -m twine upload dist/*
|
|
98
|
+
```
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
MANIFEST.in
|
|
2
2
|
README.md
|
|
3
3
|
__init__.py
|
|
4
|
+
management.py
|
|
5
|
+
oss.py
|
|
4
6
|
pyproject.toml
|
|
5
7
|
setup.py
|
|
6
8
|
./__init__.py
|
|
9
|
+
./management.py
|
|
10
|
+
./oss.py
|
|
7
11
|
./examples/__init__.py
|
|
8
12
|
./examples/list_schemas.py
|
|
9
13
|
./examples/read_remote_td.py
|
|
@@ -29,5 +33,7 @@ remote/client.py
|
|
|
29
33
|
remote/source.py
|
|
30
34
|
schema/__init__.py
|
|
31
35
|
schema/message_metadata.py
|
|
36
|
+
tests/check_management.py
|
|
37
|
+
tests/check_oss.py
|
|
32
38
|
tests/check_package.py
|
|
33
39
|
tests/check_remote.py
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"""Runnable examples for Current Data."""
|
|
1
|
+
"""Runnable examples for Current Data."""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from ..schema import SCHEMA_TO_CLASS
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if __name__ == "__main__":
|
|
5
|
-
print("SCHEMA_TO_CLASS:")
|
|
6
|
-
for schema, msg_class in SCHEMA_TO_CLASS.items():
|
|
7
|
-
print(f" {schema}: {msg_class}")
|
|
1
|
+
from ..schema import SCHEMA_TO_CLASS
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
if __name__ == "__main__":
|
|
5
|
+
print("SCHEMA_TO_CLASS:")
|
|
6
|
+
for schema, msg_class in SCHEMA_TO_CLASS.items():
|
|
7
|
+
print(f" {schema}: {msg_class}")
|
|
@@ -1,48 +1,54 @@
|
|
|
1
|
-
"""Read up to ten messages from the first matching remote TD file."""
|
|
2
|
-
|
|
3
|
-
import argparse
|
|
4
|
-
from contextlib import ExitStack, closing
|
|
5
|
-
from itertools import islice
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
from ..
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
parser
|
|
16
|
-
parser.add_argument("
|
|
17
|
-
parser.add_argument("--
|
|
18
|
-
parser.add_argument("--
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
with client.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
1
|
+
"""Read up to ten messages from the first matching remote TD file."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from contextlib import ExitStack, closing
|
|
5
|
+
from itertools import islice
|
|
6
|
+
|
|
7
|
+
import grpc
|
|
8
|
+
from google.protobuf.text_format import MessageToString
|
|
9
|
+
|
|
10
|
+
from ..remote import DataClient, MetadataFilter
|
|
11
|
+
from ..schema import SCHEMA_TO_CLASS
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main() -> None:
|
|
15
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
16
|
+
parser.add_argument("address", nargs="?", default=None, help="gRPC service address (host:port)")
|
|
17
|
+
parser.add_argument("--insecure", action="store_true", help="Use a plaintext gRPC connection instead of TLS")
|
|
18
|
+
parser.add_argument("--name-prefix", default="", help="Filter recordings by name prefix")
|
|
19
|
+
parser.add_argument("--topic", default="/head/pose/command")
|
|
20
|
+
parser.add_argument("--start-timestamp", type=int, default=0, help="Inclusive start timestamp (ns)")
|
|
21
|
+
parser.add_argument("--end-timestamp", type=int, default=2**63 - 1, help="Inclusive end timestamp (ns)")
|
|
22
|
+
args = parser.parse_args()
|
|
23
|
+
if not 0 <= args.start_timestamp <= args.end_timestamp <= 2**63 - 1:
|
|
24
|
+
parser.error("timestamps must satisfy 0 <= start <= end <= 2**63 - 1")
|
|
25
|
+
|
|
26
|
+
with ExitStack() as stack:
|
|
27
|
+
channel = grpc.insecure_channel(args.address) if args.insecure else None
|
|
28
|
+
if channel is not None:
|
|
29
|
+
stack.callback(channel.close)
|
|
30
|
+
client = stack.enter_context(DataClient(channel, address=args.address))
|
|
31
|
+
with closing(client.iter_data(MetadataFilter(name_prefix=args.name_prefix), timeout=30)) as items:
|
|
32
|
+
metadata = next(items, None)
|
|
33
|
+
if metadata is None:
|
|
34
|
+
print("No matching data")
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
with client.open_td(metadata) as reader:
|
|
38
|
+
schemas = {
|
|
39
|
+
topic.name: topic.metadata["schema_name"]
|
|
40
|
+
for group in reader.summary().topics_infos
|
|
41
|
+
for topic in group.topic_metadatas
|
|
42
|
+
}
|
|
43
|
+
messages = reader.read_messages(
|
|
44
|
+
topic_names=[args.topic],
|
|
45
|
+
start_timestamp=args.start_timestamp,
|
|
46
|
+
end_timestamp=args.end_timestamp,
|
|
47
|
+
)
|
|
48
|
+
for message in islice(messages, 10):
|
|
49
|
+
decoded = SCHEMA_TO_CLASS[schemas[message.topic_name]].FromString(message.data)
|
|
50
|
+
print(metadata.id, message.timestamp, message.topic_name, MessageToString(decoded, as_one_line=True))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __name__ == "__main__":
|
|
54
|
+
main()
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
from turbodata import FileReadSource, Reader
|
|
5
|
-
|
|
6
|
-
from ..schema import SCHEMA_TO_CLASS
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def main() -> None:
|
|
10
|
-
parser = argparse.ArgumentParser(description="Read protobuf messages from a TD file")
|
|
11
|
-
parser.add_argument("path", type=Path)
|
|
12
|
-
args = parser.parse_args()
|
|
13
|
-
|
|
14
|
-
with FileReadSource(str(args.path)) as source:
|
|
15
|
-
reader = Reader(source)
|
|
16
|
-
schemas = {
|
|
17
|
-
topic.name: topic.metadata["schema_name"]
|
|
18
|
-
for group in reader.summary().topics_infos
|
|
19
|
-
for topic in group.topic_metadatas
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
for message in reader.read_messages(topic_names=["/head/pose/command"]):
|
|
23
|
-
schema = schemas[message.topic_name]
|
|
24
|
-
msg = SCHEMA_TO_CLASS[schema]()
|
|
25
|
-
msg.ParseFromString(message.data)
|
|
26
|
-
print(message.timestamp, message.topic_name, schema, msg.position.y)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if __name__ == "__main__":
|
|
30
|
-
main()
|
|
1
|
+
import argparse
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from turbodata import FileReadSource, Reader
|
|
5
|
+
|
|
6
|
+
from ..schema import SCHEMA_TO_CLASS
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main() -> None:
|
|
10
|
+
parser = argparse.ArgumentParser(description="Read protobuf messages from a TD file")
|
|
11
|
+
parser.add_argument("path", type=Path)
|
|
12
|
+
args = parser.parse_args()
|
|
13
|
+
|
|
14
|
+
with FileReadSource(str(args.path)) as source:
|
|
15
|
+
reader = Reader(source)
|
|
16
|
+
schemas = {
|
|
17
|
+
topic.name: topic.metadata["schema_name"]
|
|
18
|
+
for group in reader.summary().topics_infos
|
|
19
|
+
for topic in group.topic_metadatas
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
for message in reader.read_messages(topic_names=["/head/pose/command"]):
|
|
23
|
+
schema = schemas[message.topic_name]
|
|
24
|
+
msg = SCHEMA_TO_CLASS[schema]()
|
|
25
|
+
msg.ParseFromString(message.data)
|
|
26
|
+
print(message.timestamp, message.topic_name, schema, msg.position.y)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
if __name__ == "__main__":
|
|
30
|
+
main()
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import time
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from turbodata import Writer
|
|
6
|
-
|
|
7
|
-
from ..schema.message_metadata import topic_metadata
|
|
8
|
-
from ..schema import Pose
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
TOPIC = "/head/pose/command"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def main() -> None:
|
|
15
|
-
parser = argparse.ArgumentParser(description="Write a protobuf message to a TD file")
|
|
16
|
-
parser.add_argument("path", type=Path)
|
|
17
|
-
args = parser.parse_args()
|
|
18
|
-
|
|
19
|
-
message = Pose()
|
|
20
|
-
message.position.y = 1.0
|
|
21
|
-
|
|
22
|
-
with args.path.open("wb") as output, Writer(output) as writer:
|
|
23
|
-
writer.open_topics([TOPIC], [topic_metadata(type(message))])
|
|
24
|
-
timestamp = time.time_ns()
|
|
25
|
-
writer.write_message(TOPIC, message.SerializeToString(), timestamp)
|
|
26
|
-
writer.close_topic()
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if __name__ == "__main__":
|
|
30
|
-
main()
|
|
1
|
+
import argparse
|
|
2
|
+
import time
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from turbodata import Writer
|
|
6
|
+
|
|
7
|
+
from ..schema.message_metadata import topic_metadata
|
|
8
|
+
from ..schema import Pose
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
TOPIC = "/head/pose/command"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main() -> None:
|
|
15
|
+
parser = argparse.ArgumentParser(description="Write a protobuf message to a TD file")
|
|
16
|
+
parser.add_argument("path", type=Path)
|
|
17
|
+
args = parser.parse_args()
|
|
18
|
+
|
|
19
|
+
message = Pose()
|
|
20
|
+
message.position.y = 1.0
|
|
21
|
+
|
|
22
|
+
with args.path.open("wb") as output, Writer(output) as writer:
|
|
23
|
+
writer.open_topics([TOPIC], [topic_metadata(type(message))])
|
|
24
|
+
timestamp = time.time_ns()
|
|
25
|
+
writer.write_message(TOPIC, message.SerializeToString(), timestamp)
|
|
26
|
+
writer.close_topic()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
if __name__ == "__main__":
|
|
30
|
+
main()
|