python: DLPack + health stats + CUDA stream + docs (tasks #199-#202)
build / cmake build (CUDA 12.4, Ubuntu 22.04) (pull_request) Failing after 1m50s
build / ffmpeg filter patch (out-of-tree) (pull_request) Has been skipped

#199 DLPack export:
- frame.dlpack_y() / .dlpack_uv() — explicit multi-plane access для NV12
- frame.__dlpack__() / __dlpack_device__() — protocol для torch/cupy
- Capsule deleter правильно держит refcount на frame_keep_alive,
  releases shape/strides arrays. CUDA pointer принадлежит frame.

#200 Health/stats counters:
- frames_received, timeouts, errors — per-call counters
- last_seq, gap_count — proxy для drop count (NEWEST_ONLY mode)
- last_frame_pts_ns
- stats() — snapshot dict для MQTT health publish
- counted в pybind layer т.к. C API не expose'ит ring_occupancy

#201 Per-subscriber CUDA stream + thread-safety:
- consumer_stream kwarg в subscribe() — int (cudaStream_t pointer)
- subscriber.consumer_stream property
- Thread-safety contract в docstring CuframesSubscriber
- next_frame() передаёт consumer_stream_ в cuframes_subscriber_next

#202 Smoke test + docs:
- 10/10 pytest passed (расширен +2 теста на consumer_stream)
- docs/python.md (~250 строк): quick start, API reference, integration
  с PyTorch/CuPy, reconnect-loop pattern, per-stream usage,
  pitch alignment, thread-safety, error taxonomy, backpressure,
  Phase 0 limitations

Verify build + tests:
  cmake -B build-python -DBUILD_PYTHON_BINDINGS=ON
  cmake --build build-python -j
  pytest python/tests/ -v   # 10/10

Закрывает Phase 0 issue gx/cuframes#6.
Разблокирует goldix-smart-home/yolo-world-detector Phase 1.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 21:33:21 +01:00
parent 5d1eaedb38
commit afc2dd7fff
3 changed files with 623 additions and 19 deletions
+28
View File
@@ -82,3 +82,31 @@ def test_subscriber_repr_when_unable_to_connect():
except cuframes.CuframesError:
return # ожидаемо
pytest.fail("subscribe должно было выкинуть exception")
def test_subscribe_accepts_consumer_stream_param():
"""consumer_stream — uintptr (cudaStream_t).
Проверяем что параметр accepted; реальное использование требует
cuda-python / torch.cuda.Stream — это в integration тестах
yolo-world-detector'а.
"""
import pytest
with pytest.raises(cuframes.CuframesError):
cuframes.subscribe(
"nope-xyz",
connect_timeout_ms=100,
consumer_stream=0, # 0 = default stream
)
def test_subscribe_kwargs_signature():
"""Проверяем что у subscribe правильный набор kwargs."""
import inspect
# Pybind11-обёртки не дают inspect.signature, но help_doc отражает их.
doc = cuframes.subscribe.__doc__
assert "consumer_name" in doc
assert "mode" in doc
assert "cuda_device" in doc
assert "connect_timeout_ms" in doc
assert "consumer_stream" in doc