quii-helper 0.1.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.
Files changed (559) hide show
  1. quii_helper-0.1.0/.env.example +35 -0
  2. quii_helper-0.1.0/.github/scripts/check_distribution.py +115 -0
  3. quii_helper-0.1.0/.github/scripts/check_install.py +150 -0
  4. quii_helper-0.1.0/.github/scripts/check_rtsp_soak.py +180 -0
  5. quii_helper-0.1.0/.github/scripts/release_gate.py +230 -0
  6. quii_helper-0.1.0/.github/workflows/ci.yml +201 -0
  7. quii_helper-0.1.0/.github/workflows/publish.yml +52 -0
  8. quii_helper-0.1.0/CHANGELOG.md +223 -0
  9. quii_helper-0.1.0/COMPATIBILITY.md +61 -0
  10. quii_helper-0.1.0/CONTRIBUTING.md +55 -0
  11. quii_helper-0.1.0/LICENSE +21 -0
  12. quii_helper-0.1.0/MANIFEST.in +10 -0
  13. quii_helper-0.1.0/PKG-INFO +243 -0
  14. quii_helper-0.1.0/README.md +213 -0
  15. quii_helper-0.1.0/RELEASE_CHECKLIST.md +181 -0
  16. quii_helper-0.1.0/SECURITY.md +30 -0
  17. quii_helper-0.1.0/docs/README.md +7 -0
  18. quii_helper-0.1.0/docs/api.md +535 -0
  19. quii_helper-0.1.0/docs/protocol-notes.md +342 -0
  20. quii_helper-0.1.0/docs/setup.md +283 -0
  21. quii_helper-0.1.0/examples/__init__.py +1 -0
  22. quii_helper-0.1.0/examples/call_events.py +27 -0
  23. quii_helper-0.1.0/examples/discover_env_values.py +48 -0
  24. quii_helper-0.1.0/examples/open_door.py +24 -0
  25. quii_helper-0.1.0/examples/save_video.py +19 -0
  26. quii_helper-0.1.0/examples/serve_rtsp.py +16 -0
  27. quii_helper-0.1.0/examples/snapshot.py +19 -0
  28. quii_helper-0.1.0/pyproject.toml +178 -0
  29. quii_helper-0.1.0/quii_helper/__init__.py +260 -0
  30. quii_helper-0.1.0/quii_helper/camera/__init__.py +246 -0
  31. quii_helper-0.1.0/quii_helper/camera/api/__init__.py +3440 -0
  32. quii_helper-0.1.0/quii_helper/camera/capture_request/__init__.py +0 -0
  33. quii_helper-0.1.0/quii_helper/camera/capture_request/request.py +65 -0
  34. quii_helper-0.1.0/quii_helper/camera/capture_request/request_state.py +28 -0
  35. quii_helper-0.1.0/quii_helper/camera/connection/__init__.py +0 -0
  36. quii_helper-0.1.0/quii_helper/camera/connection/session.py +120 -0
  37. quii_helper-0.1.0/quii_helper/camera/device_cgi/__init__.py +237 -0
  38. quii_helper-0.1.0/quii_helper/camera/device_cgi/models.py +528 -0
  39. quii_helper-0.1.0/quii_helper/camera/device_cgi/service.py +930 -0
  40. quii_helper-0.1.0/quii_helper/camera/device_json_cgi/__init__.py +117 -0
  41. quii_helper-0.1.0/quii_helper/camera/device_json_cgi/models.py +157 -0
  42. quii_helper-0.1.0/quii_helper/camera/device_json_cgi/service.py +280 -0
  43. quii_helper-0.1.0/quii_helper/camera/metadata/__init__.py +11 -0
  44. quii_helper-0.1.0/quii_helper/camera/metadata/models.py +42 -0
  45. quii_helper-0.1.0/quii_helper/camera/metadata/service.py +108 -0
  46. quii_helper-0.1.0/quii_helper/camera/outputs/__init__.py +0 -0
  47. quii_helper-0.1.0/quii_helper/camera/outputs/paths.py +19 -0
  48. quii_helper-0.1.0/quii_helper/camera/outputs/result_state.py +48 -0
  49. quii_helper-0.1.0/quii_helper/camera/outputs/results.py +114 -0
  50. quii_helper-0.1.0/quii_helper/camera/runtime/__init__.py +0 -0
  51. quii_helper-0.1.0/quii_helper/camera/runtime/capture.py +66 -0
  52. quii_helper-0.1.0/quii_helper/camera/settings/__init__.py +0 -0
  53. quii_helper-0.1.0/quii_helper/camera/settings/config.py +122 -0
  54. quii_helper-0.1.0/quii_helper/camera/settings/config_state.py +40 -0
  55. quii_helper-0.1.0/quii_helper/camera/settings/init_state.py +38 -0
  56. quii_helper-0.1.0/quii_helper/camera/settings/options.py +19 -0
  57. quii_helper-0.1.0/quii_helper/camera/streaming/__init__.py +5 -0
  58. quii_helper-0.1.0/quii_helper/camera/streaming/rtsp.py +299 -0
  59. quii_helper-0.1.0/quii_helper/cloud/__init__.py +41 -0
  60. quii_helper-0.1.0/quii_helper/cloud/alarms/__init__.py +9 -0
  61. quii_helper-0.1.0/quii_helper/cloud/alarms/client.py +219 -0
  62. quii_helper-0.1.0/quii_helper/cloud/alarms/models.py +62 -0
  63. quii_helper-0.1.0/quii_helper/cloud/alarms/service.py +133 -0
  64. quii_helper-0.1.0/quii_helper/cloud/authentication/__init__.py +0 -0
  65. quii_helper-0.1.0/quii_helper/cloud/authentication/auth.py +143 -0
  66. quii_helper-0.1.0/quii_helper/cloud/authentication/responses.py +100 -0
  67. quii_helper-0.1.0/quii_helper/cloud/config/__init__.py +0 -0
  68. quii_helper-0.1.0/quii_helper/cloud/config/defaults.py +9 -0
  69. quii_helper-0.1.0/quii_helper/cloud/config/runtime.py +73 -0
  70. quii_helper-0.1.0/quii_helper/cloud/devices/__init__.py +13 -0
  71. quii_helper-0.1.0/quii_helper/cloud/devices/models.py +18 -0
  72. quii_helper-0.1.0/quii_helper/cloud/devices/requests.py +35 -0
  73. quii_helper-0.1.0/quii_helper/cloud/devices/responses.py +73 -0
  74. quii_helper-0.1.0/quii_helper/cloud/devices/service.py +70 -0
  75. quii_helper-0.1.0/quii_helper/cloud/flows/__init__.py +0 -0
  76. quii_helper-0.1.0/quii_helper/cloud/flows/probe_flow.py +78 -0
  77. quii_helper-0.1.0/quii_helper/cloud/http/__init__.py +0 -0
  78. quii_helper-0.1.0/quii_helper/cloud/http/transport.py +170 -0
  79. quii_helper-0.1.0/quii_helper/cloud/http/xml.py +51 -0
  80. quii_helper-0.1.0/quii_helper/cloud/iot/__init__.py +39 -0
  81. quii_helper-0.1.0/quii_helper/cloud/iot/client.py +98 -0
  82. quii_helper-0.1.0/quii_helper/cloud/iot/models.py +33 -0
  83. quii_helper-0.1.0/quii_helper/cloud/iot/parser.py +101 -0
  84. quii_helper-0.1.0/quii_helper/cloud/iot/service.py +61 -0
  85. quii_helper-0.1.0/quii_helper/cloud/oauth/__init__.py +27 -0
  86. quii_helper-0.1.0/quii_helper/cloud/oauth/client.py +103 -0
  87. quii_helper-0.1.0/quii_helper/cloud/oauth/models.py +10 -0
  88. quii_helper-0.1.0/quii_helper/cloud/oauth/service.py +51 -0
  89. quii_helper-0.1.0/quii_helper/cloud/services/__init__.py +0 -0
  90. quii_helper-0.1.0/quii_helper/cloud/services/config_apply.py +29 -0
  91. quii_helper-0.1.0/quii_helper/cloud/services/discovery.py +120 -0
  92. quii_helper-0.1.0/quii_helper/cloud/services/discovery_state.py +87 -0
  93. quii_helper-0.1.0/quii_helper/cloud/services/query_parser.py +38 -0
  94. quii_helper-0.1.0/quii_helper/cloud/services/query_xml.py +25 -0
  95. quii_helper-0.1.0/quii_helper/cloud/shadow/__init__.py +33 -0
  96. quii_helper-0.1.0/quii_helper/cloud/shadow/client.py +73 -0
  97. quii_helper-0.1.0/quii_helper/cloud/shadow/models.py +65 -0
  98. quii_helper-0.1.0/quii_helper/cloud/shadow/parser.py +96 -0
  99. quii_helper-0.1.0/quii_helper/cloud/shadow/service.py +57 -0
  100. quii_helper-0.1.0/quii_helper/config/__init__.py +58 -0
  101. quii_helper-0.1.0/quii_helper/config/constants.py +42 -0
  102. quii_helper-0.1.0/quii_helper/config/models.py +249 -0
  103. quii_helper-0.1.0/quii_helper/config/settings_loader.py +224 -0
  104. quii_helper-0.1.0/quii_helper/config/validation.py +73 -0
  105. quii_helper-0.1.0/quii_helper/device/__init__.py +28 -0
  106. quii_helper-0.1.0/quii_helper/device/cgi/__init__.py +309 -0
  107. quii_helper-0.1.0/quii_helper/device/cgi/client.py +1278 -0
  108. quii_helper-0.1.0/quii_helper/device/cgi/models.py +910 -0
  109. quii_helper-0.1.0/quii_helper/device/cgi/parser.py +1356 -0
  110. quii_helper-0.1.0/quii_helper/device/control/__init__.py +157 -0
  111. quii_helper-0.1.0/quii_helper/device/http/__init__.py +0 -0
  112. quii_helper-0.1.0/quii_helper/device/http/cgi.py +15 -0
  113. quii_helper-0.1.0/quii_helper/device/http/json.py +33 -0
  114. quii_helper-0.1.0/quii_helper/device/http/transport.py +254 -0
  115. quii_helper-0.1.0/quii_helper/device/http/xml.py +37 -0
  116. quii_helper-0.1.0/quii_helper/device/json_cgi/__init__.py +153 -0
  117. quii_helper-0.1.0/quii_helper/device/json_cgi/client.py +478 -0
  118. quii_helper-0.1.0/quii_helper/device/json_cgi/models.py +410 -0
  119. quii_helper-0.1.0/quii_helper/device/json_cgi/parser.py +787 -0
  120. quii_helper-0.1.0/quii_helper/device/probes/__init__.py +0 -0
  121. quii_helper-0.1.0/quii_helper/device/probes/flow.py +56 -0
  122. quii_helper-0.1.0/quii_helper/device/probes/modes.py +126 -0
  123. quii_helper-0.1.0/quii_helper/device/security/__init__.py +0 -0
  124. quii_helper-0.1.0/quii_helper/device/security/auth.py +37 -0
  125. quii_helper-0.1.0/quii_helper/device/security/streamkey.py +23 -0
  126. quii_helper-0.1.0/quii_helper/devtools/__init__.py +29 -0
  127. quii_helper-0.1.0/quii_helper/devtools/console.py +21 -0
  128. quii_helper-0.1.0/quii_helper/devtools/preview_application.py +83 -0
  129. quii_helper-0.1.0/quii_helper/devtools/tcp_runner.py +112 -0
  130. quii_helper-0.1.0/quii_helper/diagnostics/__init__.py +19 -0
  131. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/__init__.py +31 -0
  132. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/payload/__init__.py +0 -0
  133. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/payload/inner_analysis.py +74 -0
  134. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/payload/probe.py +44 -0
  135. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/payload/probe_state.py +34 -0
  136. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/tail/__init__.py +0 -0
  137. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/tail/analysis.py +43 -0
  138. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/tail/artifacts.py +58 -0
  139. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/tail/candidate_extractors.py +78 -0
  140. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/tail/candidate_state.py +65 -0
  141. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/tail/candidates.py +23 -0
  142. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/tail/crypto.py +32 -0
  143. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/tail/probe.py +89 -0
  144. quii_helper-0.1.0/quii_helper/diagnostics/wrapped/tail/probe_state.py +63 -0
  145. quii_helper-0.1.0/quii_helper/direct/__init__.py +11 -0
  146. quii_helper-0.1.0/quii_helper/direct/p2p_mqtt.py +83 -0
  147. quii_helper-0.1.0/quii_helper/direct/p2p_request.py +51 -0
  148. quii_helper-0.1.0/quii_helper/direct/p2p_session.py +82 -0
  149. quii_helper-0.1.0/quii_helper/direct/peer_selection.py +102 -0
  150. quii_helper-0.1.0/quii_helper/direct/preview.py +112 -0
  151. quii_helper-0.1.0/quii_helper/io/__init__.py +26 -0
  152. quii_helper-0.1.0/quii_helper/io/jsonl_writer.py +11 -0
  153. quii_helper-0.1.0/quii_helper/io/output_paths.py +11 -0
  154. quii_helper-0.1.0/quii_helper/io/paths.py +95 -0
  155. quii_helper-0.1.0/quii_helper/io/safe_read.py +11 -0
  156. quii_helper-0.1.0/quii_helper/main.py +23 -0
  157. quii_helper-0.1.0/quii_helper/media/__init__.py +27 -0
  158. quii_helper-0.1.0/quii_helper/media/cpacket/__init__.py +81 -0
  159. quii_helper-0.1.0/quii_helper/media/cpacket/analysis.py +23 -0
  160. quii_helper-0.1.0/quii_helper/media/cpacket/constants.py +4 -0
  161. quii_helper-0.1.0/quii_helper/media/cpacket/header.py +115 -0
  162. quii_helper-0.1.0/quii_helper/media/cpacket/scanner.py +19 -0
  163. quii_helper-0.1.0/quii_helper/media/cpacket/stream.py +20 -0
  164. quii_helper-0.1.0/quii_helper/media/fragments/__init__.py +1 -0
  165. quii_helper-0.1.0/quii_helper/media/fragments/fragmented_media.py +101 -0
  166. quii_helper-0.1.0/quii_helper/media/fragments/state.py +114 -0
  167. quii_helper-0.1.0/quii_helper/media/frames/__init__.py +1 -0
  168. quii_helper-0.1.0/quii_helper/media/frames/assembler.py +57 -0
  169. quii_helper-0.1.0/quii_helper/media/frames/assembler_state.py +90 -0
  170. quii_helper-0.1.0/quii_helper/media/frames/cframe_pack.py +122 -0
  171. quii_helper-0.1.0/quii_helper/media/frames/cframe_pack_state.py +32 -0
  172. quii_helper-0.1.0/quii_helper/media/frames/frame_parsing.py +24 -0
  173. quii_helper-0.1.0/quii_helper/media/frames/models.py +14 -0
  174. quii_helper-0.1.0/quii_helper/media/frames/parsing.py +33 -0
  175. quii_helper-0.1.0/quii_helper/media/h264/__init__.py +1 -0
  176. quii_helper-0.1.0/quii_helper/media/h264/core/__init__.py +1 -0
  177. quii_helper-0.1.0/quii_helper/media/h264/core/analysis.py +18 -0
  178. quii_helper-0.1.0/quii_helper/media/h264/core/annexb.py +85 -0
  179. quii_helper-0.1.0/quii_helper/media/h264/io/__init__.py +1 -0
  180. quii_helper-0.1.0/quii_helper/media/h264/io/ffmpeg.py +102 -0
  181. quii_helper-0.1.0/quii_helper/media/h264/io/ffmpeg_state.py +86 -0
  182. quii_helper-0.1.0/quii_helper/media/h264/io/writer.py +115 -0
  183. quii_helper-0.1.0/quii_helper/media/h264/io/writer_state.py +102 -0
  184. quii_helper-0.1.0/quii_helper/media/h264/merge/__init__.py +1 -0
  185. quii_helper-0.1.0/quii_helper/media/h264/merge/annexb_merge.py +66 -0
  186. quii_helper-0.1.0/quii_helper/media/h264/merge/annexb_merge_state.py +99 -0
  187. quii_helper-0.1.0/quii_helper/media/h264/merge/probe_analysis.py +38 -0
  188. quii_helper-0.1.0/quii_helper/media/merge/__init__.py +1 -0
  189. quii_helper-0.1.0/quii_helper/media/merge/binary.py +41 -0
  190. quii_helper-0.1.0/quii_helper/media/merge/bytes.py +23 -0
  191. quii_helper-0.1.0/quii_helper/media/probes/__init__.py +1 -0
  192. quii_helper-0.1.0/quii_helper/media/probes/analysis.py +33 -0
  193. quii_helper-0.1.0/quii_helper/media/probes/container.py +60 -0
  194. quii_helper-0.1.0/quii_helper/models/__init__.py +1 -0
  195. quii_helper-0.1.0/quii_helper/models/capture.py +118 -0
  196. quii_helper-0.1.0/quii_helper/models/packets.py +95 -0
  197. quii_helper-0.1.0/quii_helper/network/__init__.py +161 -0
  198. quii_helper-0.1.0/quii_helper/network/lan_discovery.py +260 -0
  199. quii_helper-0.1.0/quii_helper/network/state.py +51 -0
  200. quii_helper-0.1.0/quii_helper/preview/__init__.py +21 -0
  201. quii_helper-0.1.0/quii_helper/preview/fragments/__init__.py +1 -0
  202. quii_helper-0.1.0/quii_helper/preview/fragments/collectors.py +106 -0
  203. quii_helper-0.1.0/quii_helper/preview/fragments/embedded_h264.py +75 -0
  204. quii_helper-0.1.0/quii_helper/preview/fragments/embedded_h264_state.py +82 -0
  205. quii_helper-0.1.0/quii_helper/preview/fragments/fragment_flow.py +228 -0
  206. quii_helper-0.1.0/quii_helper/preview/fragments/fragment_flow_state.py +143 -0
  207. quii_helper-0.1.0/quii_helper/preview/fragments/fragment_summary_state.py +51 -0
  208. quii_helper-0.1.0/quii_helper/preview/outputs/__init__.py +31 -0
  209. quii_helper-0.1.0/quii_helper/preview/outputs/manager/__init__.py +1 -0
  210. quii_helper-0.1.0/quii_helper/preview/outputs/manager/artifacts.py +158 -0
  211. quii_helper-0.1.0/quii_helper/preview/outputs/manager/paths.py +36 -0
  212. quii_helper-0.1.0/quii_helper/preview/outputs/manager/sample_recorder.py +26 -0
  213. quii_helper-0.1.0/quii_helper/preview/outputs/manager/state.py +87 -0
  214. quii_helper-0.1.0/quii_helper/preview/outputs/probes/__init__.py +1 -0
  215. quii_helper-0.1.0/quii_helper/preview/outputs/probes/outputs.py +74 -0
  216. quii_helper-0.1.0/quii_helper/preview/outputs/probes/state.py +75 -0
  217. quii_helper-0.1.0/quii_helper/preview/outputs/writer/__init__.py +1 -0
  218. quii_helper-0.1.0/quii_helper/preview/outputs/writer/output_writer.py +150 -0
  219. quii_helper-0.1.0/quii_helper/preview/outputs/writer/state.py +64 -0
  220. quii_helper-0.1.0/quii_helper/preview/pipeline/__init__.py +1 -0
  221. quii_helper-0.1.0/quii_helper/preview/pipeline/capture_pipeline.py +134 -0
  222. quii_helper-0.1.0/quii_helper/preview/pipeline/capture_pipeline_state.py +52 -0
  223. quii_helper-0.1.0/quii_helper/preview/pipeline/config.py +37 -0
  224. quii_helper-0.1.0/quii_helper/preview/pipeline/factory.py +108 -0
  225. quii_helper-0.1.0/quii_helper/preview/pipeline/stream.py +87 -0
  226. quii_helper-0.1.0/quii_helper/preview/processing/__init__.py +1 -0
  227. quii_helper-0.1.0/quii_helper/preview/processing/packets/__init__.py +1 -0
  228. quii_helper-0.1.0/quii_helper/preview/processing/packets/capture_stats.py +48 -0
  229. quii_helper-0.1.0/quii_helper/preview/processing/packets/decoder.py +19 -0
  230. quii_helper-0.1.0/quii_helper/preview/processing/packets/diagnostics.py +67 -0
  231. quii_helper-0.1.0/quii_helper/preview/processing/packets/diagnostics_collector.py +61 -0
  232. quii_helper-0.1.0/quii_helper/preview/processing/packets/flow.py +201 -0
  233. quii_helper-0.1.0/quii_helper/preview/processing/packets/processor.py +254 -0
  234. quii_helper-0.1.0/quii_helper/preview/processing/packets/processor_state.py +83 -0
  235. quii_helper-0.1.0/quii_helper/preview/processing/packets/recorder.py +66 -0
  236. quii_helper-0.1.0/quii_helper/preview/processing/packets/summary.py +84 -0
  237. quii_helper-0.1.0/quii_helper/preview/processing/packets/summary_state.py +31 -0
  238. quii_helper-0.1.0/quii_helper/preview/processing/payloads/__init__.py +1 -0
  239. quii_helper-0.1.0/quii_helper/preview/processing/payloads/diagnostics.py +95 -0
  240. quii_helper-0.1.0/quii_helper/preview/processing/payloads/diagnostics_state.py +25 -0
  241. quii_helper-0.1.0/quii_helper/preview/processing/summaries/__init__.py +1 -0
  242. quii_helper-0.1.0/quii_helper/preview/processing/summaries/emitter.py +38 -0
  243. quii_helper-0.1.0/quii_helper/preview/summaries/__init__.py +1 -0
  244. quii_helper-0.1.0/quii_helper/preview/summaries/capture_summary.py +80 -0
  245. quii_helper-0.1.0/quii_helper/preview/summaries/capture_summary_state.py +63 -0
  246. quii_helper-0.1.0/quii_helper/preview/summaries/media_summary.py +75 -0
  247. quii_helper-0.1.0/quii_helper/preview/summaries/media_summary_state.py +115 -0
  248. quii_helper-0.1.0/quii_helper/preview/tools/__init__.py +1 -0
  249. quii_helper-0.1.0/quii_helper/preview/tools/application.py +5 -0
  250. quii_helper-0.1.0/quii_helper/preview/tools/console.py +8 -0
  251. quii_helper-0.1.0/quii_helper/protocols/__init__.py +41 -0
  252. quii_helper-0.1.0/quii_helper/protocols/mqtt/__init__.py +16 -0
  253. quii_helper-0.1.0/quii_helper/protocols/mqtt/bootstrap.py +192 -0
  254. quii_helper-0.1.0/quii_helper/protocols/mqtt/protocol.py +18 -0
  255. quii_helper-0.1.0/quii_helper/protocols/mqtt/publishers.py +75 -0
  256. quii_helper-0.1.0/quii_helper/protocols/mqtt/runtime.py +46 -0
  257. quii_helper-0.1.0/quii_helper/protocols/mqtt/url.py +74 -0
  258. quii_helper-0.1.0/quii_helper/protocols/mqtt/waiters.py +122 -0
  259. quii_helper-0.1.0/quii_helper/protocols/p2p/__init__.py +43 -0
  260. quii_helper-0.1.0/quii_helper/protocols/p2p/codec/__init__.py +0 -0
  261. quii_helper-0.1.0/quii_helper/protocols/p2p/codec/json_codec.py +83 -0
  262. quii_helper-0.1.0/quii_helper/protocols/p2p/codec/json_state.py +75 -0
  263. quii_helper-0.1.0/quii_helper/protocols/p2p/handshake/__init__.py +0 -0
  264. quii_helper-0.1.0/quii_helper/protocols/p2p/handshake/active.py +84 -0
  265. quii_helper-0.1.0/quii_helper/protocols/p2p/messages/__init__.py +0 -0
  266. quii_helper-0.1.0/quii_helper/protocols/p2p/messages/protocol.py +63 -0
  267. quii_helper-0.1.0/quii_helper/protocols/p2p/messages/session.py +64 -0
  268. quii_helper-0.1.0/quii_helper/protocols/p2p/models/__init__.py +23 -0
  269. quii_helper-0.1.0/quii_helper/protocols/p2p/models/request.py +104 -0
  270. quii_helper-0.1.0/quii_helper/protocols/p2p/models/response.py +96 -0
  271. quii_helper-0.1.0/quii_helper/protocols/p2p/peers/__init__.py +0 -0
  272. quii_helper-0.1.0/quii_helper/protocols/p2p/peers/selection.py +66 -0
  273. quii_helper-0.1.0/quii_helper/protocols/p2p/peers/targets.py +69 -0
  274. quii_helper-0.1.0/quii_helper/protocols/p2p/probing/__init__.py +0 -0
  275. quii_helper-0.1.0/quii_helper/protocols/p2p/probing/test_packets.py +107 -0
  276. quii_helper-0.1.0/quii_helper/protocols/p2p/probing/udp_probe.py +105 -0
  277. quii_helper-0.1.0/quii_helper/protocols/p2p/transport/__init__.py +15 -0
  278. quii_helper-0.1.0/quii_helper/protocols/p2p/transport/packets.py +102 -0
  279. quii_helper-0.1.0/quii_helper/protocols/p2p/transport/udp.py +23 -0
  280. quii_helper-0.1.0/quii_helper/protocols/quii/__init__.py +27 -0
  281. quii_helper-0.1.0/quii_helper/protocols/quii/blob.py +175 -0
  282. quii_helper-0.1.0/quii_helper/protocols/quii/blob_flow.py +87 -0
  283. quii_helper-0.1.0/quii_helper/protocols/quii/crypto.py +85 -0
  284. quii_helper-0.1.0/quii_helper/protocols/quii/live_bodies.py +19 -0
  285. quii_helper-0.1.0/quii_helper/protocols/quii/live_envelope.py +71 -0
  286. quii_helper-0.1.0/quii_helper/protocols/quii/live_packets.py +155 -0
  287. quii_helper-0.1.0/quii_helper/protocols/quii/live_protocol.py +30 -0
  288. quii_helper-0.1.0/quii_helper/protocols/quii/live_rb.py +136 -0
  289. quii_helper-0.1.0/quii_helper/protocols/quii/url.py +55 -0
  290. quii_helper-0.1.0/quii_helper/protocols/rbudp/__init__.py +43 -0
  291. quii_helper-0.1.0/quii_helper/protocols/rbudp/control/__init__.py +0 -0
  292. quii_helper-0.1.0/quii_helper/protocols/rbudp/control/ack_status.py +49 -0
  293. quii_helper-0.1.0/quii_helper/protocols/rbudp/control/dispatcher.py +266 -0
  294. quii_helper-0.1.0/quii_helper/protocols/rbudp/control/flow.py +187 -0
  295. quii_helper-0.1.0/quii_helper/protocols/rbudp/control/handler.py +37 -0
  296. quii_helper-0.1.0/quii_helper/protocols/rbudp/control/handshake.py +69 -0
  297. quii_helper-0.1.0/quii_helper/protocols/rbudp/control/lane_updates.py +13 -0
  298. quii_helper-0.1.0/quii_helper/protocols/rbudp/control/packets.py +64 -0
  299. quii_helper-0.1.0/quii_helper/protocols/rbudp/control/play_status.py +51 -0
  300. quii_helper-0.1.0/quii_helper/protocols/rbudp/control/progress.py +156 -0
  301. quii_helper-0.1.0/quii_helper/protocols/rbudp/core/__init__.py +0 -0
  302. quii_helper-0.1.0/quii_helper/protocols/rbudp/core/constants.py +63 -0
  303. quii_helper-0.1.0/quii_helper/protocols/rbudp/core/models.py +73 -0
  304. quii_helper-0.1.0/quii_helper/protocols/rbudp/core/packets.py +17 -0
  305. quii_helper-0.1.0/quii_helper/protocols/rbudp/core/protocol.py +59 -0
  306. quii_helper-0.1.0/quii_helper/protocols/rbudp/core/rb_data_packets.py +68 -0
  307. quii_helper-0.1.0/quii_helper/protocols/rbudp/fragments/__init__.py +5 -0
  308. quii_helper-0.1.0/quii_helper/protocols/rbudp/fragments/ack.py +56 -0
  309. quii_helper-0.1.0/quii_helper/protocols/rbudp/fragments/flow.py +204 -0
  310. quii_helper-0.1.0/quii_helper/protocols/rbudp/fragments/gap.py +46 -0
  311. quii_helper-0.1.0/quii_helper/protocols/rbudp/fragments/packet.py +46 -0
  312. quii_helper-0.1.0/quii_helper/protocols/rbudp/fragments/partial.py +48 -0
  313. quii_helper-0.1.0/quii_helper/protocols/rbudp/fragments/remainder.py +145 -0
  314. quii_helper-0.1.0/quii_helper/protocols/rbudp/fragments/state.py +67 -0
  315. quii_helper-0.1.0/quii_helper/protocols/rbudp/fragments/stream.py +115 -0
  316. quii_helper-0.1.0/quii_helper/protocols/rbudp/kcp/__init__.py +0 -0
  317. quii_helper-0.1.0/quii_helper/protocols/rbudp/kcp/connect_packets.py +78 -0
  318. quii_helper-0.1.0/quii_helper/protocols/rbudp/kcp/frame_dispatch.py +101 -0
  319. quii_helper-0.1.0/quii_helper/protocols/rbudp/kcp/link_packets.py +27 -0
  320. quii_helper-0.1.0/quii_helper/protocols/rbudp/lanes/__init__.py +11 -0
  321. quii_helper-0.1.0/quii_helper/protocols/rbudp/lanes/control.py +138 -0
  322. quii_helper-0.1.0/quii_helper/protocols/rbudp/lanes/registry.py +152 -0
  323. quii_helper-0.1.0/quii_helper/protocols/rbudp/lanes/state.py +91 -0
  324. quii_helper-0.1.0/quii_helper/protocols/rbudp/live/__init__.py +0 -0
  325. quii_helper-0.1.0/quii_helper/protocols/rbudp/live/command_state.py +65 -0
  326. quii_helper-0.1.0/quii_helper/protocols/rbudp/live/play_probes.py +154 -0
  327. quii_helper-0.1.0/quii_helper/protocols/rbudp/live/play_stages.py +177 -0
  328. quii_helper-0.1.0/quii_helper/protocols/rbudp/live/play_sync.py +213 -0
  329. quii_helper-0.1.0/quii_helper/protocols/rbudp/live/play_sync_state.py +33 -0
  330. quii_helper-0.1.0/quii_helper/protocols/rbudp/live/sender.py +266 -0
  331. quii_helper-0.1.0/quii_helper/protocols/rbudp/receive/__init__.py +0 -0
  332. quii_helper-0.1.0/quii_helper/protocols/rbudp/receive/incoming_payload.py +210 -0
  333. quii_helper-0.1.0/quii_helper/protocols/rbudp/receive/loop.py +137 -0
  334. quii_helper-0.1.0/quii_helper/protocols/rbudp/receive/payload_queue.py +85 -0
  335. quii_helper-0.1.0/quii_helper/protocols/rbudp/receive/stream.py +259 -0
  336. quii_helper-0.1.0/quii_helper/protocols/rbudp/receive/stream_packet.py +38 -0
  337. quii_helper-0.1.0/quii_helper/protocols/rbudp/receive/stream_state.py +111 -0
  338. quii_helper-0.1.0/quii_helper/protocols/rbudp/transport/__init__.py +0 -0
  339. quii_helper-0.1.0/quii_helper/protocols/rbudp/transport/frame_handler.py +120 -0
  340. quii_helper-0.1.0/quii_helper/protocols/rbudp/transport/io.py +109 -0
  341. quii_helper-0.1.0/quii_helper/protocols/rbudp/tunnel/__init__.py +6 -0
  342. quii_helper-0.1.0/quii_helper/protocols/rbudp/tunnel/keepalive.py +74 -0
  343. quii_helper-0.1.0/quii_helper/protocols/rbudp/tunnel/lifecycle.py +112 -0
  344. quii_helper-0.1.0/quii_helper/protocols/rbudp/tunnel/session.py +727 -0
  345. quii_helper-0.1.0/quii_helper/protocols/rbudp/tunnel/state.py +58 -0
  346. quii_helper-0.1.0/quii_helper/protocols/rbudp/tunnel/threads.py +40 -0
  347. quii_helper-0.1.0/quii_helper/protocols/rbudp/wrapped/__init__.py +0 -0
  348. quii_helper-0.1.0/quii_helper/protocols/rbudp/wrapped/frame_handler.py +258 -0
  349. quii_helper-0.1.0/quii_helper/protocols/rbudp/wrapped/handler.py +83 -0
  350. quii_helper-0.1.0/quii_helper/protocols/rbudp/wrapped/lanes.py +66 -0
  351. quii_helper-0.1.0/quii_helper/protocols/rbudp/wrapped/packets.py +124 -0
  352. quii_helper-0.1.0/quii_helper/protocols/rbudp/wrapped/sender.py +169 -0
  353. quii_helper-0.1.0/quii_helper/protocols/tcp/__init__.py +25 -0
  354. quii_helper-0.1.0/quii_helper/protocols/tcp/codec/__init__.py +0 -0
  355. quii_helper-0.1.0/quii_helper/protocols/tcp/codec/message_codec.py +90 -0
  356. quii_helper-0.1.0/quii_helper/protocols/tcp/live/__init__.py +0 -0
  357. quii_helper-0.1.0/quii_helper/protocols/tcp/live/packet_builder.py +47 -0
  358. quii_helper-0.1.0/quii_helper/protocols/tcp/live/probe_capture.py +45 -0
  359. quii_helper-0.1.0/quii_helper/protocols/tcp/probes/__init__.py +0 -0
  360. quii_helper-0.1.0/quii_helper/protocols/tcp/probes/attempt.py +110 -0
  361. quii_helper-0.1.0/quii_helper/protocols/tcp/probes/candidates.py +97 -0
  362. quii_helper-0.1.0/quii_helper/protocols/tcp/probes/config_summary.py +65 -0
  363. quii_helper-0.1.0/quii_helper/protocols/tcp/probes/quii_probe.py +103 -0
  364. quii_helper-0.1.0/quii_helper/protocols/tcp/probes/results.py +119 -0
  365. quii_helper-0.1.0/quii_helper/protocols/tcp/probes/runner.py +75 -0
  366. quii_helper-0.1.0/quii_helper/protocols/tcp/probes/settings.py +48 -0
  367. quii_helper-0.1.0/quii_helper/protocols/tcp/transport/__init__.py +0 -0
  368. quii_helper-0.1.0/quii_helper/protocols/tcp/transport/client.py +135 -0
  369. quii_helper-0.1.0/quii_helper/protocols/tcp/transport/socket_transport.py +40 -0
  370. quii_helper-0.1.0/quii_helper/protocols/ust/__init__.py +23 -0
  371. quii_helper-0.1.0/quii_helper/protocols/ust/credentials.py +85 -0
  372. quii_helper-0.1.0/quii_helper/protocols/ust/crypto.py +57 -0
  373. quii_helper-0.1.0/quii_helper/protocols/ust/crypto_tables.py +84 -0
  374. quii_helper-0.1.0/quii_helper/protocols/ust/key_derivation.py +60 -0
  375. quii_helper-0.1.0/quii_helper/protocols/ust/key_schedule.py +54 -0
  376. quii_helper-0.1.0/quii_helper/protocols/ust/message_builder.py +42 -0
  377. quii_helper-0.1.0/quii_helper/protocols/ust/messages.py +122 -0
  378. quii_helper-0.1.0/quii_helper/py.typed +0 -0
  379. quii_helper-0.1.0/quii_helper/streaming/__init__.py +17 -0
  380. quii_helper-0.1.0/quii_helper/streaming/h264/__init__.py +5 -0
  381. quii_helper-0.1.0/quii_helper/streaming/h264/live.py +55 -0
  382. quii_helper-0.1.0/quii_helper/streaming/rtp/__init__.py +13 -0
  383. quii_helper-0.1.0/quii_helper/streaming/rtp/h264.py +183 -0
  384. quii_helper-0.1.0/quii_helper/streaming/rtsp/__init__.py +5 -0
  385. quii_helper-0.1.0/quii_helper/streaming/rtsp/client.py +420 -0
  386. quii_helper-0.1.0/quii_helper/streaming/rtsp/constants.py +2 -0
  387. quii_helper-0.1.0/quii_helper/streaming/rtsp/request.py +92 -0
  388. quii_helper-0.1.0/quii_helper/streaming/rtsp/sdp.py +18 -0
  389. quii_helper-0.1.0/quii_helper/streaming/rtsp/server.py +195 -0
  390. quii_helper-0.1.0/quii_helper/streaming/rtsp/transport.py +31 -0
  391. quii_helper-0.1.0/quii_helper/support/__init__.py +1 -0
  392. quii_helper-0.1.0/quii_helper/support/error_codes.py +1442 -0
  393. quii_helper-0.1.0/quii_helper/support/errors.py +25 -0
  394. quii_helper-0.1.0/quii_helper/support/log.py +51 -0
  395. quii_helper-0.1.0/quii_helper/support/redaction.py +101 -0
  396. quii_helper-0.1.0/quii_helper.egg-info/PKG-INFO +243 -0
  397. quii_helper-0.1.0/quii_helper.egg-info/SOURCES.txt +557 -0
  398. quii_helper-0.1.0/quii_helper.egg-info/dependency_links.txt +1 -0
  399. quii_helper-0.1.0/quii_helper.egg-info/requires.txt +12 -0
  400. quii_helper-0.1.0/quii_helper.egg-info/top_level.txt +1 -0
  401. quii_helper-0.1.0/setup.cfg +4 -0
  402. quii_helper-0.1.0/tests/__init__.py +1 -0
  403. quii_helper-0.1.0/tests/camera/__init__.py +1 -0
  404. quii_helper-0.1.0/tests/camera/test_camera.py +382 -0
  405. quii_helper-0.1.0/tests/camera/test_capture.py +165 -0
  406. quii_helper-0.1.0/tests/camera/test_config_state.py +74 -0
  407. quii_helper-0.1.0/tests/camera/test_connection_lifecycle.py +69 -0
  408. quii_helper-0.1.0/tests/camera/test_device_cgi.py +1919 -0
  409. quii_helper-0.1.0/tests/camera/test_device_info.py +165 -0
  410. quii_helper-0.1.0/tests/camera/test_device_json_cgi.py +745 -0
  411. quii_helper-0.1.0/tests/camera/test_door_control.py +239 -0
  412. quii_helper-0.1.0/tests/camera/test_init_state.py +37 -0
  413. quii_helper-0.1.0/tests/camera/test_request_state.py +62 -0
  414. quii_helper-0.1.0/tests/camera/test_result_state.py +104 -0
  415. quii_helper-0.1.0/tests/camera/test_rtsp_api.py +85 -0
  416. quii_helper-0.1.0/tests/camera/test_rtsp_lifecycle.py +269 -0
  417. quii_helper-0.1.0/tests/cloud/__init__.py +1 -0
  418. quii_helper-0.1.0/tests/cloud/test_auth_responses.py +170 -0
  419. quii_helper-0.1.0/tests/cloud/test_call_events.py +605 -0
  420. quii_helper-0.1.0/tests/cloud/test_cookie_isolation.py +118 -0
  421. quii_helper-0.1.0/tests/cloud/test_device_list.py +80 -0
  422. quii_helper-0.1.0/tests/cloud/test_http_transport.py +260 -0
  423. quii_helper-0.1.0/tests/cloud/test_iot_command_support.py +245 -0
  424. quii_helper-0.1.0/tests/cloud/test_oauth.py +125 -0
  425. quii_helper-0.1.0/tests/cloud/test_runtime_config.py +88 -0
  426. quii_helper-0.1.0/tests/cloud/test_service_discovery_state.py +90 -0
  427. quii_helper-0.1.0/tests/cloud/test_service_errors.py +55 -0
  428. quii_helper-0.1.0/tests/cloud/test_shadow.py +205 -0
  429. quii_helper-0.1.0/tests/config/__init__.py +1 -0
  430. quii_helper-0.1.0/tests/config/test_config.py +70 -0
  431. quii_helper-0.1.0/tests/config/test_settings_loader.py +276 -0
  432. quii_helper-0.1.0/tests/config/test_validation_state.py +51 -0
  433. quii_helper-0.1.0/tests/conftest.py +28 -0
  434. quii_helper-0.1.0/tests/device/test_cgi_readonly.py +2622 -0
  435. quii_helper-0.1.0/tests/device/test_door_control.py +327 -0
  436. quii_helper-0.1.0/tests/device/test_json_cgi_readonly.py +898 -0
  437. quii_helper-0.1.0/tests/diagnostics/__init__.py +1 -0
  438. quii_helper-0.1.0/tests/diagnostics/wrapped/__init__.py +1 -0
  439. quii_helper-0.1.0/tests/diagnostics/wrapped/payload/__init__.py +1 -0
  440. quii_helper-0.1.0/tests/diagnostics/wrapped/payload/test_probe_state.py +63 -0
  441. quii_helper-0.1.0/tests/diagnostics/wrapped/tail/__init__.py +1 -0
  442. quii_helper-0.1.0/tests/diagnostics/wrapped/tail/test_artifacts.py +70 -0
  443. quii_helper-0.1.0/tests/diagnostics/wrapped/tail/test_candidate_state.py +135 -0
  444. quii_helper-0.1.0/tests/diagnostics/wrapped/tail/test_probe.py +55 -0
  445. quii_helper-0.1.0/tests/io_helpers/__init__.py +1 -0
  446. quii_helper-0.1.0/tests/io_helpers/test_paths.py +151 -0
  447. quii_helper-0.1.0/tests/io_helpers/test_safe_read.py +23 -0
  448. quii_helper-0.1.0/tests/media/__init__.py +1 -0
  449. quii_helper-0.1.0/tests/media/fragments/__init__.py +1 -0
  450. quii_helper-0.1.0/tests/media/fragments/test_fragmented_media_state.py +139 -0
  451. quii_helper-0.1.0/tests/media/frames/__init__.py +1 -0
  452. quii_helper-0.1.0/tests/media/frames/test_assembler_state.py +113 -0
  453. quii_helper-0.1.0/tests/media/frames/test_cframe_pack_state.py +64 -0
  454. quii_helper-0.1.0/tests/media/frames/test_parsing.py +152 -0
  455. quii_helper-0.1.0/tests/media/h264/__init__.py +1 -0
  456. quii_helper-0.1.0/tests/media/h264/test_analysis.py +46 -0
  457. quii_helper-0.1.0/tests/media/h264/test_annexb_merge_state.py +84 -0
  458. quii_helper-0.1.0/tests/media/h264/test_ffmpeg.py +13 -0
  459. quii_helper-0.1.0/tests/media/h264/test_ffmpeg_state.py +107 -0
  460. quii_helper-0.1.0/tests/media/h264/test_writer.py +94 -0
  461. quii_helper-0.1.0/tests/media/h264/test_writer_state.py +130 -0
  462. quii_helper-0.1.0/tests/media/merge/__init__.py +1 -0
  463. quii_helper-0.1.0/tests/media/merge/test_bytes_merge.py +46 -0
  464. quii_helper-0.1.0/tests/models/test_capture_model_usage.py +42 -0
  465. quii_helper-0.1.0/tests/network/__init__.py +1 -0
  466. quii_helper-0.1.0/tests/network/test_lan_discovery.py +86 -0
  467. quii_helper-0.1.0/tests/network/test_state.py +60 -0
  468. quii_helper-0.1.0/tests/package/__init__.py +1 -0
  469. quii_helper-0.1.0/tests/package/test_distributions.py +123 -0
  470. quii_helper-0.1.0/tests/package/test_docstrings.py +327 -0
  471. quii_helper-0.1.0/tests/package/test_examples.py +111 -0
  472. quii_helper-0.1.0/tests/package/test_layout.py +32 -0
  473. quii_helper-0.1.0/tests/package/test_library_usage.py +129 -0
  474. quii_helper-0.1.0/tests/package/test_public_api.py +301 -0
  475. quii_helper-0.1.0/tests/package/test_release_gate.py +203 -0
  476. quii_helper-0.1.0/tests/preview/__init__.py +1 -0
  477. quii_helper-0.1.0/tests/preview/fragments/__init__.py +1 -0
  478. quii_helper-0.1.0/tests/preview/fragments/test_embedded_h264_state.py +91 -0
  479. quii_helper-0.1.0/tests/preview/fragments/test_fragment_flow_state.py +236 -0
  480. quii_helper-0.1.0/tests/preview/fragments/test_fragment_partial_collector.py +136 -0
  481. quii_helper-0.1.0/tests/preview/fragments/test_fragment_summary_state.py +64 -0
  482. quii_helper-0.1.0/tests/preview/outputs/__init__.py +1 -0
  483. quii_helper-0.1.0/tests/preview/outputs/test_artifact_manager_state.py +22 -0
  484. quii_helper-0.1.0/tests/preview/outputs/test_artifact_state.py +74 -0
  485. quii_helper-0.1.0/tests/preview/outputs/test_output_writer.py +87 -0
  486. quii_helper-0.1.0/tests/preview/outputs/test_output_writer_state.py +106 -0
  487. quii_helper-0.1.0/tests/preview/outputs/test_probe_output_state.py +97 -0
  488. quii_helper-0.1.0/tests/preview/pipeline/__init__.py +1 -0
  489. quii_helper-0.1.0/tests/preview/pipeline/test_capture_pipeline.py +170 -0
  490. quii_helper-0.1.0/tests/preview/pipeline/test_capture_pipeline_state.py +84 -0
  491. quii_helper-0.1.0/tests/preview/processing/__init__.py +1 -0
  492. quii_helper-0.1.0/tests/preview/processing/packets/__init__.py +1 -0
  493. quii_helper-0.1.0/tests/preview/processing/packets/test_capture_stats.py +142 -0
  494. quii_helper-0.1.0/tests/preview/processing/packets/test_diagnostics.py +66 -0
  495. quii_helper-0.1.0/tests/preview/processing/packets/test_flow.py +237 -0
  496. quii_helper-0.1.0/tests/preview/processing/packets/test_pending_limits.py +147 -0
  497. quii_helper-0.1.0/tests/preview/processing/packets/test_processor.py +298 -0
  498. quii_helper-0.1.0/tests/preview/processing/packets/test_processor_state.py +199 -0
  499. quii_helper-0.1.0/tests/preview/processing/packets/test_recorder.py +88 -0
  500. quii_helper-0.1.0/tests/preview/processing/packets/test_stream_partitions.py +157 -0
  501. quii_helper-0.1.0/tests/preview/processing/packets/test_summary_state.py +54 -0
  502. quii_helper-0.1.0/tests/preview/processing/payloads/__init__.py +1 -0
  503. quii_helper-0.1.0/tests/preview/processing/payloads/test_diagnostics_state.py +74 -0
  504. quii_helper-0.1.0/tests/preview/summaries/__init__.py +1 -0
  505. quii_helper-0.1.0/tests/preview/summaries/test_capture_summary.py +88 -0
  506. quii_helper-0.1.0/tests/preview/summaries/test_capture_summary_state.py +87 -0
  507. quii_helper-0.1.0/tests/preview/summaries/test_media_summary_state.py +117 -0
  508. quii_helper-0.1.0/tests/protocols/__init__.py +1 -0
  509. quii_helper-0.1.0/tests/protocols/mqtt/__init__.py +0 -0
  510. quii_helper-0.1.0/tests/protocols/mqtt/test_mro.py +12 -0
  511. quii_helper-0.1.0/tests/protocols/p2p/__init__.py +1 -0
  512. quii_helper-0.1.0/tests/protocols/p2p/test_json_codec.py +111 -0
  513. quii_helper-0.1.0/tests/protocols/p2p/test_models.py +111 -0
  514. quii_helper-0.1.0/tests/protocols/p2p/test_targets.py +51 -0
  515. quii_helper-0.1.0/tests/protocols/quii/__init__.py +1 -0
  516. quii_helper-0.1.0/tests/protocols/quii/test_blob_flow.py +111 -0
  517. quii_helper-0.1.0/tests/protocols/quii/test_crypto.py +67 -0
  518. quii_helper-0.1.0/tests/protocols/rbudp/__init__.py +1 -0
  519. quii_helper-0.1.0/tests/protocols/rbudp/test_control_dispatcher.py +140 -0
  520. quii_helper-0.1.0/tests/protocols/rbudp/test_control_handshake_flow.py +125 -0
  521. quii_helper-0.1.0/tests/protocols/rbudp/test_control_status_components.py +165 -0
  522. quii_helper-0.1.0/tests/protocols/rbudp/test_fragment_state.py +96 -0
  523. quii_helper-0.1.0/tests/protocols/rbudp/test_incoming_payload.py +192 -0
  524. quii_helper-0.1.0/tests/protocols/rbudp/test_lane_control.py +101 -0
  525. quii_helper-0.1.0/tests/protocols/rbudp/test_lane_registry.py +56 -0
  526. quii_helper-0.1.0/tests/protocols/rbudp/test_lane_state.py +45 -0
  527. quii_helper-0.1.0/tests/protocols/rbudp/test_live_command_state.py +108 -0
  528. quii_helper-0.1.0/tests/protocols/rbudp/test_live_sender.py +102 -0
  529. quii_helper-0.1.0/tests/protocols/rbudp/test_payload_queue.py +311 -0
  530. quii_helper-0.1.0/tests/protocols/rbudp/test_play_components.py +144 -0
  531. quii_helper-0.1.0/tests/protocols/rbudp/test_play_sync_state.py +49 -0
  532. quii_helper-0.1.0/tests/protocols/rbudp/test_receive_limits.py +106 -0
  533. quii_helper-0.1.0/tests/protocols/rbudp/test_receive_regressions.py +192 -0
  534. quii_helper-0.1.0/tests/protocols/rbudp/test_receive_stream_packet.py +39 -0
  535. quii_helper-0.1.0/tests/protocols/rbudp/test_receive_stream_state.py +120 -0
  536. quii_helper-0.1.0/tests/protocols/rbudp/test_remote_disconnect.py +130 -0
  537. quii_helper-0.1.0/tests/protocols/rbudp/test_transport_frame.py +129 -0
  538. quii_helper-0.1.0/tests/protocols/rbudp/test_tunnel_lifecycle.py +130 -0
  539. quii_helper-0.1.0/tests/protocols/rbudp/test_tunnel_mro.py +143 -0
  540. quii_helper-0.1.0/tests/protocols/rbudp/test_tunnel_session.py +49 -0
  541. quii_helper-0.1.0/tests/protocols/rbudp/test_tunnel_state.py +81 -0
  542. quii_helper-0.1.0/tests/protocols/rbudp/test_tunnel_threads.py +33 -0
  543. quii_helper-0.1.0/tests/protocols/rbudp/test_wire_format.py +136 -0
  544. quii_helper-0.1.0/tests/protocols/rbudp/test_wrapped_diagnostics.py +87 -0
  545. quii_helper-0.1.0/tests/protocols/rbudp/test_wrapped_flow.py +313 -0
  546. quii_helper-0.1.0/tests/protocols/ust/__init__.py +0 -0
  547. quii_helper-0.1.0/tests/protocols/ust/test_asset_paths.py +160 -0
  548. quii_helper-0.1.0/tests/protocols/ust/test_crypto_exports.py +10 -0
  549. quii_helper-0.1.0/tests/streaming/__init__.py +0 -0
  550. quii_helper-0.1.0/tests/streaming/test_h264_live.py +77 -0
  551. quii_helper-0.1.0/tests/streaming/test_rtp_h264.py +72 -0
  552. quii_helper-0.1.0/tests/streaming/test_rtsp_backpressure.py +137 -0
  553. quii_helper-0.1.0/tests/streaming/test_rtsp_requests.py +199 -0
  554. quii_helper-0.1.0/tests/streaming/test_rtsp_server.py +119 -0
  555. quii_helper-0.1.0/tests/support/__init__.py +1 -0
  556. quii_helper-0.1.0/tests/support/test_error_codes.py +54 -0
  557. quii_helper-0.1.0/tests/support/test_logging.py +73 -0
  558. quii_helper-0.1.0/tests/support/test_redaction.py +68 -0
  559. quii_helper-0.1.0/tests/test_errors.py +52 -0
@@ -0,0 +1,35 @@
1
+ # Mobile-app account credentials. CLOUD_USERNAME is also accepted as a legacy
2
+ # alias for CLOUD_ACCOUNT.
3
+ CLOUD_ACCOUNT=""
4
+ CLOUD_PASSWORD=""
5
+ DEVICE_ID=""
6
+ CAMERA_DEVICE_HOST=""
7
+
8
+ # Stable per-install client id. Generate one with:
9
+ # python -c "import uuid; print(uuid.uuid4().hex)"
10
+ CLOUD_CLIENT_UUID=""
11
+
12
+ # Camera/app identity and cloud endpoints extracted from the APK or discovered
13
+ # with: python -m examples.discover_env_values
14
+ CLOUD_AUTH_URL=""
15
+ CLOUD_SERVICE_URL=""
16
+ CAMERA_OEM=""
17
+ CAMERA_APP_ID=
18
+ CAMERA_CLIENT_TYPE=
19
+ IP_REGION_ID=
20
+ CLOUD_AUTH_VERSION=""
21
+
22
+ CAMERA_CHANNEL=1
23
+ CAMERA_STREAM=2
24
+
25
+ # Optional. AUTH_CODE is used by local /tdkcgi helpers and TCP/CGI
26
+ # probe helpers, not by the normal cloud/P2P preview flow.
27
+ AUTH_CODE=""
28
+ DEVICE_PASSWORD=""
29
+
30
+ # Required only by Camera.open_door(). This is the door-opening password,
31
+ # separate from AUTH_CODE, DEVICE_PASSWORD, and CLOUD_PASSWORD.
32
+ UNLOCK_PASSWORD="" # Optional.
33
+
34
+ TLS_VERIFY=true
35
+ LOG_LEVEL=info
@@ -0,0 +1,115 @@
1
+ """Reject incomplete/private release archives and mismatched release tags."""
2
+
3
+ import os
4
+ import sys
5
+ import tarfile
6
+ import zipfile
7
+ from email.parser import BytesParser
8
+ from pathlib import Path, PurePosixPath
9
+
10
+ from packaging.version import Version
11
+
12
+
13
+ def check_tag(tag: str, version: str) -> None:
14
+ """Require a v-prefixed tag whose PEP 440 version matches the package."""
15
+ if not tag.startswith("v") or Version(tag[1:]) != Version(version):
16
+ raise ValueError("release tag does not match distribution version")
17
+
18
+
19
+ def check_members(names: set[str]) -> None:
20
+ """Keep credentials, extracted binaries and generated data out of archives."""
21
+ for name in names:
22
+ path = PurePosixPath(name)
23
+ if path.is_absolute() or ".." in path.parts or "\\" in name:
24
+ raise ValueError("unsafe archive member")
25
+ if (
26
+ set(path.parts)
27
+ & {"assets", "data", "venv", ".venv", "__pycache__"}
28
+ or any(
29
+ part.startswith(".env") and part != ".env.example"
30
+ for part in path.parts
31
+ )
32
+ or path.suffix.lower()
33
+ in {".pem", ".key", ".so", ".pyc", ".mp4", ".jpg", ".h264", ".log"}
34
+ ):
35
+ raise ValueError("private or generated file in distribution")
36
+
37
+
38
+ def check_distributions(directory: Path, tag: str = "") -> str:
39
+ """Check both archives, SPDX metadata, type marker and source parity."""
40
+ wheels = list(directory.glob("*.whl"))
41
+ sources = list(directory.glob("*.tar.gz"))
42
+ if len(wheels) != 1 or len(sources) != 1:
43
+ raise ValueError("expected exactly one wheel and one sdist")
44
+ with zipfile.ZipFile(wheels[0]) as archive:
45
+ wheel = {name: archive.read(name) for name in archive.namelist()}
46
+ with tarfile.open(sources[0]) as archive:
47
+ source = {}
48
+ for member in archive.getmembers():
49
+ if not member.isfile():
50
+ if not member.isdir():
51
+ raise ValueError("links or special files in sdist")
52
+ continue
53
+ stream = archive.extractfile(member)
54
+ if stream is not None:
55
+ source[member.name] = stream.read()
56
+ check_members(set(wheel) | set(source))
57
+ metadata_names = [
58
+ name for name in wheel if name.endswith(".dist-info/METADATA")
59
+ ]
60
+ if len(metadata_names) != 1:
61
+ raise ValueError("expected one wheel metadata record")
62
+ metadata_path = PurePosixPath(metadata_names[0])
63
+ metadata = BytesParser().parsebytes(wheel[str(metadata_path)])
64
+ version = metadata["Version"]
65
+ if (
66
+ metadata["Name"] != "quii-helper"
67
+ or metadata["License-Expression"] != "MIT"
68
+ or metadata.get_all("License-File") != ["LICENSE"]
69
+ or str(metadata_path.parent / "licenses/LICENSE") not in wheel
70
+ ):
71
+ raise ValueError("missing package identity or SPDX license metadata")
72
+ root = "quii_helper-" + version + "/"
73
+ required = {
74
+ "PKG-INFO",
75
+ "LICENSE",
76
+ "README.md",
77
+ ".env.example",
78
+ "pyproject.toml",
79
+ "docs/README.md",
80
+ "examples/snapshot.py",
81
+ "tests/package/test_public_api.py",
82
+ ".github/scripts/check_distribution.py",
83
+ }
84
+ if not all(root + name in source for name in required):
85
+ raise ValueError("sdist is missing required sources or documentation")
86
+ source_metadata = BytesParser().parsebytes(source[root + "PKG-INFO"])
87
+ if source_metadata["Version"] != version:
88
+ raise ValueError("wheel and sdist versions differ")
89
+ package = {
90
+ name: data
91
+ for name, data in wheel.items()
92
+ if name.startswith("quii_helper/")
93
+ }
94
+ source_package = {
95
+ name[len(root) :]: data
96
+ for name, data in source.items()
97
+ if name.startswith(root + "quii_helper/")
98
+ }
99
+ if "quii_helper/py.typed" not in package or package != source_package:
100
+ raise ValueError("wheel and sdist package contents differ")
101
+ if tag:
102
+ check_tag(tag, version)
103
+ return version
104
+
105
+
106
+ if __name__ == "__main__":
107
+ release_tag = (
108
+ os.environ.get("GITHUB_REF_NAME", "")
109
+ if os.environ.get("GITHUB_REF_TYPE") == "tag"
110
+ else ""
111
+ )
112
+ print(
113
+ "Checked distributions:",
114
+ check_distributions(Path(sys.argv[1]), release_tag),
115
+ )
@@ -0,0 +1,150 @@
1
+ """Install both archives outside the checkout without camera or cloud I/O."""
2
+
3
+ import argparse
4
+ import importlib.metadata
5
+ import shutil
6
+ import subprocess
7
+ import sys
8
+ import tempfile
9
+ import venv
10
+ from pathlib import Path
11
+ from unittest.mock import patch
12
+
13
+
14
+ def smoke() -> None:
15
+ """Verify installed imports, explicit configuration and host logging."""
16
+ from loguru import logger
17
+
18
+ Path(".env").write_text("CAMERA_APP_ID=invalid\n", encoding="utf-8")
19
+ messages: list[str] = []
20
+ sink = logger.add(lambda message: messages.append(str(message)))
21
+ with (
22
+ patch(
23
+ "dotenv.dotenv_values",
24
+ side_effect=AssertionError("implicit env read"),
25
+ ),
26
+ patch(
27
+ "dotenv.load_dotenv",
28
+ side_effect=AssertionError("implicit env load"),
29
+ ),
30
+ patch("socket.socket.connect", side_effect=AssertionError("network")),
31
+ patch("socket.socket.sendto", side_effect=AssertionError("network")),
32
+ patch("threading.Thread.start", side_effect=AssertionError("thread")),
33
+ patch(
34
+ "pathlib.Path.mkdir", side_effect=AssertionError("directory write")
35
+ ),
36
+ ):
37
+ import quii_helper
38
+ from quii_helper import AutonomousConfig, Camera
39
+
40
+ package = Path(quii_helper.__file__).resolve().parent
41
+ assert package.is_relative_to(Path(sys.prefix).resolve())
42
+ assert (package / "py.typed").is_file()
43
+ camera = Camera(AutonomousConfig(app_id=17))
44
+ assert camera.config.app_id == 17
45
+ assert camera.data_dir == (Path.cwd() / "data").resolve()
46
+ assert camera.config.assets_dir == (Path.cwd() / "assets").resolve()
47
+ logger.info("host sink survived")
48
+ logger.remove(sink)
49
+ assert len(messages) == 1 and "host sink survived" in messages[0]
50
+ assert not Path("data").exists() and not Path("assets").exists()
51
+ print("Installed library OK:", importlib.metadata.version("quii-helper"))
52
+
53
+
54
+ def check_install(directory: Path, *, soak_seconds: float = 0) -> None:
55
+ """Install wheel and sdist into distinct disposable virtual environments."""
56
+ for suffix in ("*.whl", "*.tar.gz"):
57
+ artifacts = list(directory.resolve().glob(suffix))
58
+ if len(artifacts) != 1:
59
+ raise ValueError("expected one artifact of each distribution type")
60
+ with tempfile.TemporaryDirectory(prefix="quii-install-") as temporary:
61
+ root = Path(temporary)
62
+ venv.EnvBuilder(with_pip=True).create(root / "env")
63
+ executable = (
64
+ root
65
+ / "env"
66
+ / (
67
+ "Scripts/python.exe"
68
+ if sys.platform == "win32"
69
+ else "bin/python"
70
+ )
71
+ )
72
+ subprocess.run(
73
+ [str(executable), "-m", "pip", "install", str(artifacts[0])],
74
+ cwd=root,
75
+ check=True,
76
+ )
77
+ subprocess.run(
78
+ [str(executable), "-m", "pip", "check"], cwd=root, check=True
79
+ )
80
+ subprocess.run(
81
+ [
82
+ str(executable),
83
+ "-I",
84
+ str(Path(__file__).resolve()),
85
+ "--smoke",
86
+ ],
87
+ cwd=root,
88
+ check=True,
89
+ )
90
+ # Test the installed artifact, not an editable checkout.
91
+ subprocess.run(
92
+ [
93
+ str(executable),
94
+ "-m",
95
+ "pip",
96
+ "install",
97
+ f"{artifacts[0]}[dev]",
98
+ ],
99
+ cwd=root,
100
+ check=True,
101
+ )
102
+ source = Path(__file__).resolve().parents[2]
103
+ consumer = root / "consumer"
104
+ consumer.mkdir()
105
+ shutil.copytree(source / "examples", consumer / "examples")
106
+ subprocess.run(
107
+ [
108
+ str(executable),
109
+ "-I",
110
+ "-B",
111
+ "-c",
112
+ "import sys; from pathlib import Path; "
113
+ "sys.path.insert(0, str(Path.cwd())); "
114
+ "import quii_helper, pytest; "
115
+ "assert Path(quii_helper.__file__).resolve().is_relative_to("
116
+ "Path(sys.prefix).resolve()); "
117
+ "raise SystemExit(pytest.main(['-q', '--import-mode=importlib', "
118
+ "'-p', 'no:cacheprovider', sys.argv[1]]))",
119
+ str(source / "tests"),
120
+ ],
121
+ cwd=consumer,
122
+ check=True,
123
+ )
124
+ if suffix == "*.whl" and soak_seconds:
125
+ subprocess.run(
126
+ [
127
+ str(executable),
128
+ "-I",
129
+ "-B",
130
+ str(source / ".github/scripts/check_rtsp_soak.py"),
131
+ "--seconds",
132
+ str(soak_seconds),
133
+ ],
134
+ cwd=consumer,
135
+ check=True,
136
+ )
137
+ subprocess.run(
138
+ [str(executable), "-m", "pip", "check"], cwd=root, check=True
139
+ )
140
+
141
+
142
+ if __name__ == "__main__":
143
+ if sys.argv[1:] == ["--smoke"]:
144
+ smoke()
145
+ else:
146
+ parser = argparse.ArgumentParser(description=__doc__)
147
+ parser.add_argument("directory", type=Path)
148
+ parser.add_argument("--soak-seconds", type=float, default=0)
149
+ arguments = parser.parse_args()
150
+ check_install(arguments.directory, soak_seconds=arguments.soak_seconds)
@@ -0,0 +1,180 @@
1
+ """Exercise the installed RTSP server with synthetic loopback-only video."""
2
+
3
+ import argparse
4
+ import gc
5
+ import json
6
+ import socket
7
+ import threading
8
+ import time
9
+ import tracemalloc
10
+
11
+ from quii_helper.streaming.rtsp.server import RtspH264Server
12
+
13
+
14
+ def read_exact(sock: socket.socket, size: int) -> bytes:
15
+ data = bytearray()
16
+ while len(data) < size:
17
+ chunk = sock.recv(size - len(data))
18
+ if not chunk:
19
+ raise EOFError("RTSP viewer disconnected")
20
+ data.extend(chunk)
21
+ return bytes(data)
22
+
23
+
24
+ class Viewer:
25
+ """A real TCP viewer; the slow variant deliberately never reads RTP."""
26
+
27
+ def __init__(self, server: RtspH264Server, *, slow: bool = False):
28
+ self.sock = socket.socket()
29
+ self.sock.settimeout(3)
30
+ if slow:
31
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024)
32
+ self.sock.connect(("127.0.0.1", server.port))
33
+ self.stopped = threading.Event()
34
+ self.packets = 0
35
+ self.frames = 0
36
+ self.error: BaseException | None = None
37
+ self.thread: threading.Thread | None = None
38
+ try:
39
+ for cseq, method in enumerate(("SETUP", "PLAY"), 1):
40
+ request = (
41
+ f"{method} {server.url} RTSP/1.0\r\nCSeq: {cseq}\r\n"
42
+ "Transport: RTP/AVP/TCP;unicast;interleaved=0-1\r\n\r\n"
43
+ )
44
+ self.sock.sendall(request.encode("ascii"))
45
+ response = bytearray()
46
+ while not response.endswith(b"\r\n\r\n"):
47
+ response.extend(read_exact(self.sock, 1))
48
+ if len(response) > 4096:
49
+ raise AssertionError("oversized RTSP response")
50
+ assert response.startswith(b"RTSP/1.0 200 "), response
51
+ self.sock.settimeout(0.5)
52
+ if not slow:
53
+ self.thread = threading.Thread(
54
+ target=self._receive, name="release-gate-viewer"
55
+ )
56
+ self.thread.start()
57
+ except BaseException:
58
+ self.close()
59
+ raise
60
+
61
+ def _receive(self) -> None:
62
+ previous_sequence = None
63
+ try:
64
+ while not self.stopped.is_set():
65
+ try:
66
+ header = read_exact(self.sock, 4)
67
+ except socket.timeout:
68
+ continue
69
+ assert header[:2] == b"$\0", header
70
+ packet = read_exact(
71
+ self.sock, int.from_bytes(header[2:], "big")
72
+ )
73
+ assert len(packet) >= 12 and packet[0] == 0x80
74
+ sequence = int.from_bytes(packet[2:4], "big")
75
+ if previous_sequence is not None:
76
+ assert sequence == (previous_sequence + 1) & 0xFFFF
77
+ previous_sequence = sequence
78
+ self.packets += 1
79
+ self.frames += bool(packet[1] & 0x80)
80
+ except BaseException as exc:
81
+ if not self.stopped.is_set():
82
+ self.error = exc
83
+
84
+ def close(self) -> None:
85
+ self.stopped.set()
86
+ try:
87
+ self.sock.shutdown(socket.SHUT_RDWR)
88
+ except OSError:
89
+ pass
90
+ self.sock.close()
91
+ if self.thread is not None:
92
+ self.thread.join(2)
93
+ assert not self.thread.is_alive(), "viewer thread leaked"
94
+
95
+
96
+ def run_soak(seconds: float) -> dict[str, object]:
97
+ """Bound retained Python memory and exercise shutdown every 30 seconds."""
98
+ if seconds < 3:
99
+ raise ValueError("soak duration must be at least 3 seconds")
100
+ unit = b"\0\0\0\1\x65" + b"x" * (16 * 1024)
101
+ frames = packets = cycles = slow_disconnects = 0
102
+ started = time.monotonic()
103
+ deadline = started + seconds
104
+ baseline = None
105
+ growth = 0
106
+ tracemalloc.start()
107
+ try:
108
+ while time.monotonic() < deadline:
109
+ server = RtspH264Server(host="127.0.0.1", port=0).start()
110
+ fast = slow = None
111
+ workers = [server._accept_thread]
112
+ try:
113
+ fast = Viewer(server)
114
+ slow = Viewer(server, slow=True)
115
+ with server._clients_lock:
116
+ clients = list(server._clients)
117
+ for client in clients:
118
+ workers.extend([client._thread, client._sender_thread])
119
+ if client.address[1] == slow.sock.getsockname()[1]:
120
+ client.sock.setsockopt(
121
+ socket.SOL_SOCKET, socket.SO_SNDBUF, 1024
122
+ )
123
+ cycle_started = time.monotonic()
124
+ cycle_end = min(deadline, cycle_started + 30)
125
+ slow_checked = False
126
+ while time.monotonic() < cycle_end:
127
+ server.publish(unit)
128
+ assert fast.error is None, repr(fast.error)
129
+ with server._clients_lock:
130
+ assert all(
131
+ client._outgoing_bytes <= 4 * 1024 * 1024
132
+ for client in server._clients
133
+ )
134
+ if time.monotonic() - cycle_started >= 2:
135
+ assert server.client_count == 1, "slow viewer retained"
136
+ slow_checked = True
137
+ time.sleep(0.1)
138
+ assert fast.frames > 0, "fast viewer received no media"
139
+ assert fast.error is None, repr(fast.error)
140
+ frames += fast.frames
141
+ packets += fast.packets
142
+ slow_disconnects += slow_checked
143
+ finally:
144
+ for viewer in (fast, slow):
145
+ if viewer is not None:
146
+ viewer.close()
147
+ server.close()
148
+ for worker in workers:
149
+ if worker is not None:
150
+ worker.join(2)
151
+ assert not worker.is_alive(), worker.name
152
+ cycles += 1
153
+ gc.collect()
154
+ retained, _ = tracemalloc.get_traced_memory()
155
+ if baseline is None:
156
+ baseline = retained
157
+ growth = max(growth, retained - baseline)
158
+ assert growth <= 8 * 1024 * 1024, "retained Python memory grew"
159
+ _, peak = tracemalloc.get_traced_memory()
160
+ finally:
161
+ tracemalloc.stop()
162
+ assert slow_disconnects > 0, "slow-client test did not run"
163
+ return {
164
+ "elapsed_seconds": round(time.monotonic() - started, 3),
165
+ "cycles": cycles,
166
+ "received_frames": frames,
167
+ "received_rtp_packets": packets,
168
+ "slow_disconnects": slow_disconnects,
169
+ "retained_python_growth_bytes": growth,
170
+ "peak_traced_python_bytes": peak,
171
+ "worker_cleanup": "passed",
172
+ "scope": "synthetic loopback TCP; not camera, codec, UDP or RSS proof",
173
+ }
174
+
175
+
176
+ if __name__ == "__main__":
177
+ parser = argparse.ArgumentParser(description=__doc__)
178
+ parser.add_argument("--seconds", type=float, default=120)
179
+ arguments = parser.parse_args()
180
+ print(json.dumps(run_soak(arguments.seconds), indent=2))