topicforge 0.5.6__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {topicforge-0.5.6 → topicforge-0.6.0}/CHANGELOG.md +63 -1
- {topicforge-0.5.6 → topicforge-0.6.0}/PKG-INFO +7 -6
- {topicforge-0.5.6 → topicforge-0.6.0}/README.md +5 -5
- {topicforge-0.5.6 → topicforge-0.6.0}/docs/TESTING.md +3 -3
- {topicforge-0.5.6 → topicforge-0.6.0}/docs/TROUBLESHOOTING.md +2 -2
- {topicforge-0.5.6 → topicforge-0.6.0}/pyproject.toml +2 -1
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/__init__.py +1 -1
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/base.py +3 -3
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/composite.py +4 -3
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/dds_cyclone/adapter.py +3 -2
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/dds_dust/adapter.py +3 -3
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/dds_fast/adapter.py +3 -2
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/dds_opendds/adapter.py +3 -3
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/ros2_live/adapter.py +193 -156
- topicforge-0.6.0/src/topicforge/adapters/ros2_live/echo_parser.py +165 -0
- topicforge-0.6.0/src/topicforge/adapters/ros2_live/echo_stream.py +195 -0
- topicforge-0.6.0/src/topicforge/adapters/ros2_live/process_tree.py +193 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/ros2_mock/adapter.py +11 -5
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/ros2_mock/fixtures.py +19 -8
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/constants.py +12 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/models/schemas.py +37 -19
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/services/factory.py +3 -1
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/services/inspector.py +28 -24
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/tools/handlers.py +75 -35
- topicforge-0.6.0/tests/fixtures/ros2_echo/image_noarr.yaml +24 -0
- topicforge-0.6.0/tests/fixtures/ros2_echo/image_trunc4.yaml +17 -0
- topicforge-0.6.0/tests/fixtures/ros2_echo/scan_edge.yaml +38 -0
- topicforge-0.6.0/tests/fixtures/ros2_echo/scan_noarr.yaml +30 -0
- topicforge-0.6.0/tests/fixtures/ros2_echo/scan_trunc128.yaml +273 -0
- topicforge-0.6.0/tests/fixtures/ros2_echo/scan_trunc3.yaml +46 -0
- topicforge-0.6.0/tests/fixtures/ros2_echo/string_latched.yaml +2 -0
- topicforge-0.6.0/tests/fixtures/ros2_echo/twist.yaml +18 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/integration/ros2/publisher.py +10 -0
- topicforge-0.6.0/tests/integration/ros2/test_live_adapter.py +285 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_composite_adapter.py +8 -5
- topicforge-0.6.0/tests/test_echo_parser.py +201 -0
- topicforge-0.6.0/tests/test_echo_stream.py +247 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_live_adapter_graph.py +67 -83
- topicforge-0.6.0/tests/test_live_adapter_parse.py +103 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_live_adapter_subprocess.py +112 -50
- topicforge-0.6.0/tests/test_live_sample_notes.py +150 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_mock_adapter.py +28 -2
- topicforge-0.6.0/tests/test_process_tree.py +209 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_sample_options.py +76 -16
- topicforge-0.5.6/tests/fixtures/csv_echo_imu.txt +0 -12
- topicforge-0.5.6/tests/fixtures/csv_echo_pose_multi.txt +0 -9
- topicforge-0.5.6/tests/integration/ros2/test_live_adapter.py +0 -191
- topicforge-0.5.6/tests/test_live_adapter_parse.py +0 -276
- {topicforge-0.5.6 → topicforge-0.6.0}/.gitignore +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/LICENSE +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/docs/DDS_QUICKSTART.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/docs/TUTORIEL.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/docs/dds-interop-matrix.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/00_hello_pub_sub/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/01_who_is_on_the_bus/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/02_why_cant_they_talk/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/03_a_node_crashed/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/04_late_joiner_misses_data/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/05_reliability_in_code/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/06_durability_late_joiner_in_code/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/07_deadline_in_code/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/08_crash_seen_from_inside/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/10_lidar_silent_after_driver_swap/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/11_who_talks_to_whom/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/12_safety_monitor_dropout/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/13_deadline_not_offered/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/14_restart_loop/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/examples/dds/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/agent_eval/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/integration/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/integration/publishers/cyclone_c/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/integration/publishers/cyclone_cpp/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/integration/publishers/cyclone_rust/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/integration/publishers/dust_py/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/integration/publishers/fast_publisher_cpp/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/integration/publishers/fast_py/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/integration/publishers/opensplice_publisher/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/integration/publishers/rti_c/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/scripts/integration/publishers/rti_cpp/README.md +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/__main__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/cdr_decoder.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/dds_helpers.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/dds_introspection.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/discovery_tracker.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/endpoints.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/lifecycle.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/metrics_buffer.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/qos_analyzer.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/qos_endpoints.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/qos_normalize.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/qos_scan.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/topic_filter.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/common/xtypes.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/dds_cyclone/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/dds_dust/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/dds_fast/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/dds_opendds/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/ros2_live/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/ros2_live/parsers.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/adapters/ros2_mock/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/config/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/config/settings.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/models/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/server/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/server/app.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/services/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/services/bag_service.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/services/bag_stats.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/services/health.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/services/sample_budget.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/telemetry/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/telemetry/client.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/src/topicforge/tools/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/conftest.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/fixtures/ros2_topic_info_verbose_cmd_vel.txt +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/fixtures/ros2_topic_info_verbose_parameter_events.txt +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/fixtures/ros2_topic_info_verbose_scan.txt +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/fixtures/ros2_topic_info_verbose_tf.txt +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/fixtures/ros2_topic_info_verbose_tf_static.txt +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/integration/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/integration/ros2/Dockerfile +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/integration/ros2/__init__.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/integration/ros2/entrypoint.sh +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/integration/ros2/run_bench.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/integration/test_real_bus.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_analyze_bag_multi_format.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_bag_omnisim_humble.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_bag_service.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_bag_stats.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_cdr_decoder.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_config.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_cyclone_adapter.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_dds_cross_vendor.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_dds_helpers.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_dds_inactive_reason.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_dds_introspection.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_dds_qos_normalization.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_dds_schemas.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_discovery_tracker.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_dust_adapter.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_endpoints.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_example_node_spec.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_factory.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_fast_adapter.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_health.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_history_and_hints.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_honest_outputs.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_inspector.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_lifecycle_buffer.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_metrics_buffer.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_opendds_adapter.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_peek_bag_samples.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_qos_analyzer.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_qos_endpoints.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_qos_scan.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_telemetry.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_tools_integration.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_topic_metrics.py +0 -0
- {topicforge-0.5.6 → topicforge-0.6.0}/tests/test_xtypes.py +0 -0
|
@@ -5,6 +5,67 @@ All notable changes to TopicForge are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.6.0] - 2026-10-05
|
|
9
|
+
|
|
10
|
+
`sample_messages` (live) rewritten after the OmniSim team's report (count
|
|
11
|
+
ignored, empty results on latched topics, wrong timestamps and shifted columns
|
|
12
|
+
on simulated time).
|
|
13
|
+
|
|
14
|
+
### Breaking
|
|
15
|
+
|
|
16
|
+
- `sample_messages` payloads are nested named fields (`payload.header.stamp.sec`,
|
|
17
|
+
`payload.ranges`) instead of positional `col_0`, `col_1`, ... columns. The
|
|
18
|
+
verbatim row under `_raw_text` is gone: it is present only when a message could
|
|
19
|
+
not be parsed.
|
|
20
|
+
- `_truncated_after_columns` and `_truncated_columns` are replaced by
|
|
21
|
+
`_truncated_fields`, a list of dotted field paths (`["ranges", "intensities"]`)
|
|
22
|
+
for arrays, strings or bytes cut at `max_array_length`. A cut array no longer
|
|
23
|
+
carries the CLI's `'...'` element.
|
|
24
|
+
- `nan`, `inf` and `-inf` floats are returned as the strings `"nan"`, `"inf"`,
|
|
25
|
+
`"-inf"`.
|
|
26
|
+
- `MiddlewareAdapter.sample_messages` returns a `SampleResult` instead of a list
|
|
27
|
+
of `MessageSample` and takes `timeout_s`. `parse_csv_echo` and `parse_echo_yaml`
|
|
28
|
+
are removed.
|
|
29
|
+
- `pyyaml>=6` is a runtime dependency.
|
|
30
|
+
- A failing `ros2 topic echo` (non-zero exit with no message, or a CLI that cannot
|
|
31
|
+
be started) raises an MCP error instead of returning an empty list. `count` 0 now
|
|
32
|
+
validates the topic in live mode too, as it already did in the mock.
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- `sample_messages` parameter `timeout_s` (1..45, default 10): a wall deadline for
|
|
37
|
+
the whole call, topic lookup included. The call returns within about `timeout_s`
|
|
38
|
+
plus 2 s (stopping the CLI, decoding what arrived).
|
|
39
|
+
- `MessageSample.stamp_source` (`header` or `none`) and `received_ns` (wall clock
|
|
40
|
+
when TopicForge read the message).
|
|
41
|
+
- A short result carries a `note` (`N of M messages within T s`) that tells "no
|
|
42
|
+
publisher is announced" from "a publisher exists but nothing arrived in time",
|
|
43
|
+
hints `count` 1 for a latched topic, and gives the exit code and stderr when the
|
|
44
|
+
CLI exited early.
|
|
45
|
+
- A message over the per-message size cap (`TOPICFORGE_MAX_SAMPLE_BYTES`, 1 MiB) is
|
|
46
|
+
dropped while it streams and counted in the `note`, so a large `Image` no longer
|
|
47
|
+
costs tens of seconds of YAML decoding. Decoding uses libyaml when available and
|
|
48
|
+
stops at the call deadline.
|
|
49
|
+
- `count` above 50 is capped with a note, and the tool schema declares the
|
|
50
|
+
maximum.
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- `sample_messages` honours `count`: it streams `ros2 topic echo` and stops at
|
|
55
|
+
`count` messages or the deadline, then stops the process tree (SIGINT then
|
|
56
|
+
SIGKILL on POSIX, `taskkill /F /T` on Windows) (OmniSim D3). The echo is
|
|
57
|
+
started with explicit `--qos-reliability` and `--qos-durability` taken from the
|
|
58
|
+
publishers, so a latched (`transient_local`) topic is no longer returned empty
|
|
59
|
+
because the CLI picked its QoS against a cold daemon.
|
|
60
|
+
- Stopping the CLI kills the whole process tree even when the launcher already
|
|
61
|
+
exited (POSIX: always signals the process group; Windows: a Job Object), so no
|
|
62
|
+
orphan `ros2` process keeps running. The CLI is started with UTF-8 output.
|
|
63
|
+
- The mock `sample_messages` matches the live shape: headerless messages have
|
|
64
|
+
`timestamp_ns` 0 and `stamp_source` `none`.
|
|
65
|
+
- `timestamp_ns` is the top-level `header.stamp` whatever its value, so a
|
|
66
|
+
simulated clock (seconds since the simulation start) no longer falls back to 0
|
|
67
|
+
and shifts every following column by two (OmniSim D4).
|
|
68
|
+
|
|
8
69
|
## [0.5.6] - 2026-10-02
|
|
9
70
|
|
|
10
71
|
Fixes from a live run of 0.5.3 and 0.5.5 against OmniSim's simulated
|
|
@@ -1202,7 +1263,8 @@ Initial MVP release of TopicForge: ROS Topic Inspector & Bag Analyzer MCP server
|
|
|
1202
1263
|
- The write path (publishing, commanding robots) is intentionally out of scope for the MVP.
|
|
1203
1264
|
- `analyze_bag` in live mode parses `ros2 bag info` text output; deeper anomaly detection remains mock-only for now.
|
|
1204
1265
|
|
|
1205
|
-
[Unreleased]: https://github.com/yaniswav/TopicForge/compare/v0.
|
|
1266
|
+
[Unreleased]: https://github.com/yaniswav/TopicForge/compare/v0.6.0...HEAD
|
|
1267
|
+
[0.6.0]: https://github.com/yaniswav/TopicForge/compare/v0.5.6...v0.6.0
|
|
1206
1268
|
[0.5.6]: https://github.com/yaniswav/TopicForge/compare/v0.5.5...v0.5.6
|
|
1207
1269
|
[0.5.5]: https://github.com/yaniswav/TopicForge/compare/v0.5.4...v0.5.5
|
|
1208
1270
|
[0.5.4]: https://github.com/yaniswav/TopicForge/compare/v0.5.3...v0.5.4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: topicforge
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: ROS Topic Inspector & Bag Analyzer MCP server for AI agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/yaniswav/TopicForge
|
|
6
6
|
Project-URL: Repository, https://github.com/yaniswav/TopicForge
|
|
@@ -42,6 +42,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
42
42
|
Requires-Python: >=3.10
|
|
43
43
|
Requires-Dist: mcp<2,>=1.0.0
|
|
44
44
|
Requires-Dist: pydantic>=2.6
|
|
45
|
+
Requires-Dist: pyyaml>=6
|
|
45
46
|
Provides-Extra: all
|
|
46
47
|
Requires-Dist: cyclonedds>=0.10; extra == 'all'
|
|
47
48
|
Provides-Extra: bags
|
|
@@ -108,8 +109,8 @@ Every response except `health_check` carries `mode_effective` (`"live"` or `"moc
|
|
|
108
109
|
| `health_check` | Environment and mode introspection. Always succeeds; reports `mode` next to `requested_mode` |
|
|
109
110
|
| `list_topics` | Discover the ROS2 graph |
|
|
110
111
|
| `get_topic_info` | Message type, publisher/subscriber counts and QoS for one topic |
|
|
111
|
-
| `sample_messages` | Peek recent messages on a ROS2 topic (count
|
|
112
|
-
| `analyze_bag` | Summarize a `.mcap` / `.db3` recording or `rosbag2_*` directory (via `ros2 bag info`)
|
|
112
|
+
| `sample_messages` | Peek recent messages on a ROS2 topic (count capped at 50) |
|
|
113
|
+
| `analyze_bag` | Summarize a `.mcap` / `.db3` recording or `rosbag2_*` directory (via `ros2 bag info`) |
|
|
113
114
|
| `list_participants` | DDS participants on the domain: vendor, `name` (EntityName QoS, Cyclone) and `hostname` |
|
|
114
115
|
| `detect_qos_mismatches` | Incompatible QoS pairs between DDS readers and writers |
|
|
115
116
|
| `peek_dds_samples` | Raw DDS samples; structured on the three builtin discovery topics, presence-only on user topics |
|
|
@@ -159,12 +160,12 @@ Samples with comments are in [`.env.example`](.env.example). Any invalid value s
|
|
|
159
160
|
|
|
160
161
|
- DDS validation is partial. The Cyclone adapter has run against a real bus, with Cyclone and Dust DDS participants, on Windows and in CI on Ubuntu and Windows (`.github/workflows/demo.yml`). The Fast DDS adapter has never run against a bus, and no RTI, OpenDDS, CoreDX or OpenSplice participant has been observed by this project. The multi-vendor claim rests on the RTPS protocol guarantee, not on a recorded cross-vendor run.
|
|
161
162
|
- User-topic payloads are not decoded. `peek_dds_samples` on a user topic returns count 0 and a note that the topic is announced on the bus; no traffic is read. `topic_metrics` therefore has data only for the builtin discovery topics and says so in its `status`. It is a discovery-layer probe, not a publish-rate monitor.
|
|
162
|
-
- Liveliness at runtime is not observed. A writer that is alive but silent (a hung process whose lease is still renewed) looks healthy, because TopicForge reads discovery, not data. An opt-in data probe is planned
|
|
163
|
+
- Liveliness at runtime is not observed. A writer that is alive but silent (a hung process whose lease is still renewed) looks healthy, because TopicForge reads discovery, not data. An opt-in data probe is planned. A crash and a clean leave cannot be told apart, and `lost_ns` is an upper bound of the death.
|
|
163
164
|
- Cyclone vendor ids: participants that do not follow the RTPS vendor-id convention in their GUID prefix (Dust DDS, and RTI by default) are reported with vendor `unknown`.
|
|
164
165
|
- Single domain: the server observes the domain it joined at startup; changing it needs a restart.
|
|
165
166
|
- DDS Security is not handled. A participant without credentials sees an empty secure bus. `detect_qos_mismatches` checks Partition, type name, Reliability, Durability, Deadline, Liveliness, LatencyBudget, Ownership (kind), DestinationOrder and DataRepresentation (History as a risk); Presentation, XTypes assignability and runtime behavior are not checked, and the result lists them in `policies_unchecked`. It returns a `MismatchScan` envelope: read `reports` for the mismatches.
|
|
166
167
|
- Fast DDS serves no `list_endpoints`.
|
|
167
|
-
- `sample_messages` (live)
|
|
168
|
+
- `sample_messages` (live) streams `ros2 topic echo` until `count` messages arrive or `timeout_s` (1..45, default 10, for the whole call) runs out, and returns what arrived with a `note` (`N of M messages within T s`, saying whether a publisher exists). QoS is matched to the publishers, so latched topics work. The payload has nested named fields (`payload.header.stamp.sec`); `timestamp_ns` is `header.stamp` (the publisher's clock, sim time on a simulation) or 0 for headerless types, with `stamp_source` and `received_ns` (wall clock when the CLI printed it). Arrays are cut at 128 elements by default; `max_array_length` (1..65536, or null for no cut) and `arrays_summary_only` change that, and a cut is listed under `_truncated_fields`. `nan` and `inf` come back as strings. `count` above 50 is capped with a note.
|
|
168
169
|
- `analyze_bag` (live) parses `ros2 bag info` text for the totals and counts; anomaly detection is mock-only. Per-topic times, rates (`(n - 1) / span`) and `latched` are added when the bag can be read locally (`.db3` with the standard library, `.mcap` with `rosbags`), else rates fall back to count / bag duration (`frequency_basis`). `peek_bag_samples` reads the file itself, through `rosbags`, and is served only by the ROS2 CLI adapter or the mock; bags that embed no message definitions (Humble `.db3`) are decoded with the Humble definitions, or the distro the bag records, and `note` says so. Without `ros2`, bag tools return fixtures: check `health_check` for `mode: "mock"` before trusting bag output.
|
|
169
170
|
- Synchronous handlers: the tools run on the MCP event loop; on Windows a hung `ros2` launcher can block the server.
|
|
170
171
|
- No streaming or push subscriptions: tools are strictly request/response.
|
|
@@ -188,7 +189,7 @@ When on, each tool call emits one event with exactly six fields:
|
|
|
188
189
|
| `tool_name` | `"list_topics"` | One of the twelve tools, never argument values |
|
|
189
190
|
| `latency_ms` | `12.34` | Handler wall-clock duration, 2 decimals |
|
|
190
191
|
| `mode` | `"mock"` | Mode of the adapter actually serving: `mock` or `live` |
|
|
191
|
-
| `version` | `"0.
|
|
192
|
+
| `version` | `"0.6.0"` | TopicForge server version |
|
|
192
193
|
| `session_id` | `"a1b2c3..."` | Random UUID per process, never persisted |
|
|
193
194
|
| `success` | `true` | Whether the handler returned or raised |
|
|
194
195
|
|
|
@@ -49,8 +49,8 @@ Every response except `health_check` carries `mode_effective` (`"live"` or `"moc
|
|
|
49
49
|
| `health_check` | Environment and mode introspection. Always succeeds; reports `mode` next to `requested_mode` |
|
|
50
50
|
| `list_topics` | Discover the ROS2 graph |
|
|
51
51
|
| `get_topic_info` | Message type, publisher/subscriber counts and QoS for one topic |
|
|
52
|
-
| `sample_messages` | Peek recent messages on a ROS2 topic (count
|
|
53
|
-
| `analyze_bag` | Summarize a `.mcap` / `.db3` recording or `rosbag2_*` directory (via `ros2 bag info`)
|
|
52
|
+
| `sample_messages` | Peek recent messages on a ROS2 topic (count capped at 50) |
|
|
53
|
+
| `analyze_bag` | Summarize a `.mcap` / `.db3` recording or `rosbag2_*` directory (via `ros2 bag info`) |
|
|
54
54
|
| `list_participants` | DDS participants on the domain: vendor, `name` (EntityName QoS, Cyclone) and `hostname` |
|
|
55
55
|
| `detect_qos_mismatches` | Incompatible QoS pairs between DDS readers and writers |
|
|
56
56
|
| `peek_dds_samples` | Raw DDS samples; structured on the three builtin discovery topics, presence-only on user topics |
|
|
@@ -100,12 +100,12 @@ Samples with comments are in [`.env.example`](.env.example). Any invalid value s
|
|
|
100
100
|
|
|
101
101
|
- DDS validation is partial. The Cyclone adapter has run against a real bus, with Cyclone and Dust DDS participants, on Windows and in CI on Ubuntu and Windows (`.github/workflows/demo.yml`). The Fast DDS adapter has never run against a bus, and no RTI, OpenDDS, CoreDX or OpenSplice participant has been observed by this project. The multi-vendor claim rests on the RTPS protocol guarantee, not on a recorded cross-vendor run.
|
|
102
102
|
- User-topic payloads are not decoded. `peek_dds_samples` on a user topic returns count 0 and a note that the topic is announced on the bus; no traffic is read. `topic_metrics` therefore has data only for the builtin discovery topics and says so in its `status`. It is a discovery-layer probe, not a publish-rate monitor.
|
|
103
|
-
- Liveliness at runtime is not observed. A writer that is alive but silent (a hung process whose lease is still renewed) looks healthy, because TopicForge reads discovery, not data. An opt-in data probe is planned
|
|
103
|
+
- Liveliness at runtime is not observed. A writer that is alive but silent (a hung process whose lease is still renewed) looks healthy, because TopicForge reads discovery, not data. An opt-in data probe is planned. A crash and a clean leave cannot be told apart, and `lost_ns` is an upper bound of the death.
|
|
104
104
|
- Cyclone vendor ids: participants that do not follow the RTPS vendor-id convention in their GUID prefix (Dust DDS, and RTI by default) are reported with vendor `unknown`.
|
|
105
105
|
- Single domain: the server observes the domain it joined at startup; changing it needs a restart.
|
|
106
106
|
- DDS Security is not handled. A participant without credentials sees an empty secure bus. `detect_qos_mismatches` checks Partition, type name, Reliability, Durability, Deadline, Liveliness, LatencyBudget, Ownership (kind), DestinationOrder and DataRepresentation (History as a risk); Presentation, XTypes assignability and runtime behavior are not checked, and the result lists them in `policies_unchecked`. It returns a `MismatchScan` envelope: read `reports` for the mismatches.
|
|
107
107
|
- Fast DDS serves no `list_endpoints`.
|
|
108
|
-
- `sample_messages` (live)
|
|
108
|
+
- `sample_messages` (live) streams `ros2 topic echo` until `count` messages arrive or `timeout_s` (1..45, default 10, for the whole call) runs out, and returns what arrived with a `note` (`N of M messages within T s`, saying whether a publisher exists). QoS is matched to the publishers, so latched topics work. The payload has nested named fields (`payload.header.stamp.sec`); `timestamp_ns` is `header.stamp` (the publisher's clock, sim time on a simulation) or 0 for headerless types, with `stamp_source` and `received_ns` (wall clock when the CLI printed it). Arrays are cut at 128 elements by default; `max_array_length` (1..65536, or null for no cut) and `arrays_summary_only` change that, and a cut is listed under `_truncated_fields`. `nan` and `inf` come back as strings. `count` above 50 is capped with a note.
|
|
109
109
|
- `analyze_bag` (live) parses `ros2 bag info` text for the totals and counts; anomaly detection is mock-only. Per-topic times, rates (`(n - 1) / span`) and `latched` are added when the bag can be read locally (`.db3` with the standard library, `.mcap` with `rosbags`), else rates fall back to count / bag duration (`frequency_basis`). `peek_bag_samples` reads the file itself, through `rosbags`, and is served only by the ROS2 CLI adapter or the mock; bags that embed no message definitions (Humble `.db3`) are decoded with the Humble definitions, or the distro the bag records, and `note` says so. Without `ros2`, bag tools return fixtures: check `health_check` for `mode: "mock"` before trusting bag output.
|
|
110
110
|
- Synchronous handlers: the tools run on the MCP event loop; on Windows a hung `ros2` launcher can block the server.
|
|
111
111
|
- No streaming or push subscriptions: tools are strictly request/response.
|
|
@@ -129,7 +129,7 @@ When on, each tool call emits one event with exactly six fields:
|
|
|
129
129
|
| `tool_name` | `"list_topics"` | One of the twelve tools, never argument values |
|
|
130
130
|
| `latency_ms` | `12.34` | Handler wall-clock duration, 2 decimals |
|
|
131
131
|
| `mode` | `"mock"` | Mode of the adapter actually serving: `mock` or `live` |
|
|
132
|
-
| `version` | `"0.
|
|
132
|
+
| `version` | `"0.6.0"` | TopicForge server version |
|
|
133
133
|
| `session_id` | `"a1b2c3..."` | Random UUID per process, never persisted |
|
|
134
134
|
| `success` | `true` | Whether the handler returned or raised |
|
|
135
135
|
|
|
@@ -15,7 +15,7 @@ How to get a working ROS2 environment to point TopicForge at, and how to wire it
|
|
|
15
15
|
```bash
|
|
16
16
|
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\Activate.ps1
|
|
17
17
|
pip install topicforge
|
|
18
|
-
python -m topicforge --version # -> topicforge 0.
|
|
18
|
+
python -m topicforge --version # -> topicforge 0.6.0
|
|
19
19
|
TOPICFORGE_MODE=mock python -m topicforge # blocks on stdio; MCP clients spawn it
|
|
20
20
|
```
|
|
21
21
|
|
|
@@ -41,7 +41,7 @@ python3 -m venv ~/topicforge-venv && source ~/topicforge-venv/bin/activate
|
|
|
41
41
|
pip install topicforge # Ubuntu 22.04 ships Python 3.10, which is enough
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Then run live mode with three terminals. In the first, `ros2 run demo_nodes_cpp talker` publishes `/chatter` at about 1 Hz. In the second, `ros2 topic list` should show `/chatter`. In the third, source ROS2, activate the venv and run `TOPICFORGE_MODE=live python -m topicforge`. The startup line reads `topicforge 0.
|
|
44
|
+
Then run live mode with three terminals. In the first, `ros2 run demo_nodes_cpp talker` publishes `/chatter` at about 1 Hz. In the second, `ros2 topic list` should show `/chatter`. In the third, source ROS2, activate the venv and run `TOPICFORGE_MODE=live python -m topicforge`. The startup line reads `topicforge 0.6.0 ready (mode=live, requested_mode=live, adapter=ros2_cli, telemetry=off)`; `mode=mock` means `ros2` was not found and the server fell back to fixtures.
|
|
45
45
|
|
|
46
46
|
## Linux native
|
|
47
47
|
|
|
@@ -77,7 +77,7 @@ TopicForge resolves the `ros2` launcher with `shutil.which` (normally `ros2.exe`
|
|
|
77
77
|
|
|
78
78
|
Discover the graph. Ask "What topics are currently being published, and what message types do they carry?" TopicForge calls `list_topics`. Live mode shows `/chatter` plus `/rosout` and `/parameter_events`; mock mode shows `/cmd_vel`, `/odom`, `/scan`, `/tf` and `/camera/image_raw`.
|
|
79
79
|
|
|
80
|
-
Inspect and sample. Ask "Show me the latest message on /chatter." TopicForge calls `get_topic_info` then `sample_messages`. The payload
|
|
80
|
+
Inspect and sample. Ask "Show me the latest message on /chatter." TopicForge calls `get_topic_info` then `sample_messages`. The payload has the message fields as nested named values. `timestamp_ns` is the `header.stamp` and `0` for headerless types such as `std_msgs/String` (`stamp_source` says which).
|
|
81
81
|
|
|
82
82
|
Record and analyze a bag.
|
|
83
83
|
|
|
@@ -63,12 +63,12 @@ The adapter was written against the 2.6.x binding and has never run against a bu
|
|
|
63
63
|
- `lookback_seconds must be in 1..86400` (`participant_events`): default 300. The lifecycle buffer keeps at most 200 events, newest first, regardless of window.
|
|
64
64
|
- `window_seconds must be in 1..3600` (`topic_metrics`): default 60. The buffer holds 1000 samples per topic, drop-oldest, so frequency is computed from buffered samples, not a true rolling window.
|
|
65
65
|
- `DDS topic name is malformed`: DDS names match `^[A-Za-z_/][A-Za-z0-9_/:]*$` (builtin names like `DCPSParticipant` and `::` separators are allowed; whitespace and dashes are not). ROS2 names start with `/` and use `_`, so `my-topic` becomes `/my_topic`.
|
|
66
|
-
- `sample_messages`
|
|
66
|
+
- `sample_messages` caps `count` at 50 and says so in `note`; `peek_*` clamp silently. The `count` field of the result is what was actually returned.
|
|
67
67
|
|
|
68
68
|
## Other
|
|
69
69
|
|
|
70
70
|
- `topicforge: command not found`: the entry point is not on PATH. Re-activate the venv, or use `python -m topicforge`.
|
|
71
|
-
- `sample_messages` returns
|
|
71
|
+
- `sample_messages` returns fewer samples than asked: live mode waits `timeout_s` seconds (default 10, max 60, counted from the start of the `ros2` CLI, which can take a few seconds on a slow machine) and `note` says `N of M messages` and whether a publisher exists. Raise `timeout_s` for a topic slower than 1 Hz; check `ros2 topic info -v <topic>`.
|
|
72
72
|
- `analyze_bag` says the path does not exist: the path is resolved in the shell where TopicForge runs. Under WSL use `/mnt/c/demos/run.mcap`, not `C:\demos\run.mcap`. In mock mode only `.mcap`, `.db3`, `.bag` or extensionless paths are accepted.
|
|
73
73
|
- Claude Desktop shows no tools: check Help -> View Logs -> MCP, confirm `topicforge --version` runs from the same environment (or use the absolute path of the binary in the config), and validate the config with `python -m json.tool claude_desktop_config.json`, since a JSON error silently drops the whole file.
|
|
74
74
|
- First live call is slow: `ros2 topic list -t` initializes the DDS middleware, a 1-2 second warm-up.
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "topicforge"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.6.0"
|
|
8
8
|
description = "ROS Topic Inspector & Bag Analyzer MCP server for AI agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -25,6 +25,7 @@ classifiers = [
|
|
|
25
25
|
dependencies = [
|
|
26
26
|
"mcp>=1.0.0,<2",
|
|
27
27
|
"pydantic>=2.6",
|
|
28
|
+
"pyyaml>=6",
|
|
28
29
|
]
|
|
29
30
|
|
|
30
31
|
[project.optional-dependencies]
|
|
@@ -9,11 +9,10 @@ from __future__ import annotations
|
|
|
9
9
|
|
|
10
10
|
from typing import Literal, Protocol, runtime_checkable
|
|
11
11
|
|
|
12
|
-
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH
|
|
12
|
+
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH, DEFAULT_SAMPLE_TIMEOUT_S
|
|
13
13
|
from topicforge.models import (
|
|
14
14
|
BagAnalysis,
|
|
15
15
|
EndpointListing,
|
|
16
|
-
MessageSample,
|
|
17
16
|
MismatchScan,
|
|
18
17
|
ParticipantEvent,
|
|
19
18
|
ParticipantInfo,
|
|
@@ -96,7 +95,8 @@ class MiddlewareAdapter(Protocol):
|
|
|
96
95
|
*,
|
|
97
96
|
max_array_length: int | None = DEFAULT_MAX_ARRAY_LENGTH,
|
|
98
97
|
arrays_summary_only: bool = False,
|
|
99
|
-
|
|
98
|
+
timeout_s: float = DEFAULT_SAMPLE_TIMEOUT_S,
|
|
99
|
+
) -> SampleResult: ...
|
|
100
100
|
|
|
101
101
|
def analyze_bag(self, path: str) -> BagAnalysis: ...
|
|
102
102
|
|
|
@@ -15,11 +15,10 @@ from __future__ import annotations
|
|
|
15
15
|
from typing import Any
|
|
16
16
|
|
|
17
17
|
from topicforge.adapters.base import AdapterName, EffectiveMode, MiddlewareAdapter
|
|
18
|
-
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH
|
|
18
|
+
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH, DEFAULT_SAMPLE_TIMEOUT_S
|
|
19
19
|
from topicforge.models import (
|
|
20
20
|
BagAnalysis,
|
|
21
21
|
EndpointListing,
|
|
22
|
-
MessageSample,
|
|
23
22
|
MismatchScan,
|
|
24
23
|
ParticipantEvent,
|
|
25
24
|
ParticipantInfo,
|
|
@@ -69,12 +68,14 @@ class CompositeAdapter:
|
|
|
69
68
|
*,
|
|
70
69
|
max_array_length: int | None = DEFAULT_MAX_ARRAY_LENGTH,
|
|
71
70
|
arrays_summary_only: bool = False,
|
|
72
|
-
|
|
71
|
+
timeout_s: float = DEFAULT_SAMPLE_TIMEOUT_S,
|
|
72
|
+
) -> SampleResult:
|
|
73
73
|
return self._ros.sample_messages(
|
|
74
74
|
topic,
|
|
75
75
|
count,
|
|
76
76
|
max_array_length=max_array_length,
|
|
77
77
|
arrays_summary_only=arrays_summary_only,
|
|
78
|
+
timeout_s=timeout_s,
|
|
78
79
|
)
|
|
79
80
|
|
|
80
81
|
def analyze_bag(self, path: str) -> BagAnalysis:
|
|
@@ -63,7 +63,7 @@ from topicforge.adapters.common import (
|
|
|
63
63
|
from topicforge.adapters.common import (
|
|
64
64
|
cyclone_extract_topic_name as _extract_topic_name,
|
|
65
65
|
)
|
|
66
|
-
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH
|
|
66
|
+
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH, DEFAULT_SAMPLE_TIMEOUT_S
|
|
67
67
|
from topicforge.models import (
|
|
68
68
|
BagAnalysis,
|
|
69
69
|
EndpointListing,
|
|
@@ -334,7 +334,8 @@ class CycloneDdsAdapter:
|
|
|
334
334
|
*,
|
|
335
335
|
max_array_length: int | None = DEFAULT_MAX_ARRAY_LENGTH,
|
|
336
336
|
arrays_summary_only: bool = False,
|
|
337
|
-
|
|
337
|
+
timeout_s: float = DEFAULT_SAMPLE_TIMEOUT_S,
|
|
338
|
+
) -> SampleResult:
|
|
338
339
|
raise AdapterError(DDS_ONLY_ERROR_MSG)
|
|
339
340
|
|
|
340
341
|
def analyze_bag(self, path: str) -> BagAnalysis:
|
|
@@ -12,11 +12,10 @@ import logging
|
|
|
12
12
|
|
|
13
13
|
from topicforge.adapters.base import AdapterError, AdapterName, EffectiveMode
|
|
14
14
|
from topicforge.adapters.common import validate_domain_id
|
|
15
|
-
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH
|
|
15
|
+
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH, DEFAULT_SAMPLE_TIMEOUT_S
|
|
16
16
|
from topicforge.models import (
|
|
17
17
|
BagAnalysis,
|
|
18
18
|
EndpointListing,
|
|
19
|
-
MessageSample,
|
|
20
19
|
MismatchScan,
|
|
21
20
|
ParticipantEvent,
|
|
22
21
|
ParticipantInfo,
|
|
@@ -66,7 +65,8 @@ class DustDdsAdapter:
|
|
|
66
65
|
*,
|
|
67
66
|
max_array_length: int | None = DEFAULT_MAX_ARRAY_LENGTH,
|
|
68
67
|
arrays_summary_only: bool = False,
|
|
69
|
-
|
|
68
|
+
timeout_s: float = DEFAULT_SAMPLE_TIMEOUT_S,
|
|
69
|
+
) -> SampleResult:
|
|
70
70
|
raise AdapterError(_DUST_ROADMAP_MSG)
|
|
71
71
|
|
|
72
72
|
def analyze_bag(self, path: str) -> BagAnalysis:
|
|
@@ -52,7 +52,7 @@ from topicforge.adapters.common import (
|
|
|
52
52
|
from topicforge.adapters.common import (
|
|
53
53
|
is_removal as _is_removal,
|
|
54
54
|
)
|
|
55
|
-
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH
|
|
55
|
+
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH, DEFAULT_SAMPLE_TIMEOUT_S
|
|
56
56
|
from topicforge.models import (
|
|
57
57
|
BagAnalysis,
|
|
58
58
|
EndpointListing,
|
|
@@ -241,7 +241,8 @@ class FastDdsAdapter:
|
|
|
241
241
|
*,
|
|
242
242
|
max_array_length: int | None = DEFAULT_MAX_ARRAY_LENGTH,
|
|
243
243
|
arrays_summary_only: bool = False,
|
|
244
|
-
|
|
244
|
+
timeout_s: float = DEFAULT_SAMPLE_TIMEOUT_S,
|
|
245
|
+
) -> SampleResult:
|
|
245
246
|
raise AdapterError(DDS_ONLY_ERROR_MSG)
|
|
246
247
|
|
|
247
248
|
def analyze_bag(self, path: str) -> BagAnalysis:
|
|
@@ -16,11 +16,10 @@ import logging
|
|
|
16
16
|
|
|
17
17
|
from topicforge.adapters.base import AdapterError, AdapterName, EffectiveMode
|
|
18
18
|
from topicforge.adapters.common import validate_domain_id
|
|
19
|
-
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH
|
|
19
|
+
from topicforge.constants import DEFAULT_MAX_ARRAY_LENGTH, DEFAULT_SAMPLE_TIMEOUT_S
|
|
20
20
|
from topicforge.models import (
|
|
21
21
|
BagAnalysis,
|
|
22
22
|
EndpointListing,
|
|
23
|
-
MessageSample,
|
|
24
23
|
MismatchScan,
|
|
25
24
|
ParticipantEvent,
|
|
26
25
|
ParticipantInfo,
|
|
@@ -72,7 +71,8 @@ class OpenDdsAdapter:
|
|
|
72
71
|
*,
|
|
73
72
|
max_array_length: int | None = DEFAULT_MAX_ARRAY_LENGTH,
|
|
74
73
|
arrays_summary_only: bool = False,
|
|
75
|
-
|
|
74
|
+
timeout_s: float = DEFAULT_SAMPLE_TIMEOUT_S,
|
|
75
|
+
) -> SampleResult:
|
|
76
76
|
raise AdapterError(_OPENDDS_ROADMAP_MSG)
|
|
77
77
|
|
|
78
78
|
def analyze_bag(self, path: str) -> BagAnalysis:
|