python-aidot-cameras 0.7.34__tar.gz → 0.7.36__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.
- {python_aidot_cameras-0.7.34/src/python_aidot_cameras.egg-info → python_aidot_cameras-0.7.36}/PKG-INFO +1 -1
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/pyproject.toml +1 -1
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/client.py +36 -7
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36/src/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/python_aidot_cameras.egg-info/SOURCES.txt +1 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_sdes_serve_audio.py +22 -0
- python_aidot_cameras-0.7.36/tests/test_stream_teardown.py +75 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/LICENSE +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/MANIFEST.in +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/README.md +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/setup.cfg +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/__init__.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/aes_utils.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/__init__.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/constants.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/controls.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/go2rtc.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/lan_control.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/models.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/playback.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/protocol.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/sdes.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/tutk.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/camera/webrtc.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/client.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/const.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/credentials.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/device_client.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/discover.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/exceptions.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/g711.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/login_const.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/models/__init__.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/models/device_client_model.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/models/device_model.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/models/discover_model.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/py.typed +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/python_aidot_cameras.egg-info/requires.txt +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/python_aidot_cameras.egg-info/top_level.txt +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_alarm_event.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_backoff.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_device_login_guard.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_go2rtc.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_highport_nomination.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_lan_control.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_live_stream_param.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_motion_poll.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_no_undefined_names.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_persistent_mqtt.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_post_merge_hardening.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_sdes_adaptive.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_sdes_fast_liveplay.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_sdes_idle_release.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_sdes_serve_cmd.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_sdes_sprop.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_sdes_talk.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_sdes_watchdog.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_serve_relay.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_speak.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_stream_cap.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_stream_idle.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_talk.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_terminal_ack.py +0 -0
- {python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_token_refresh.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-aidot-cameras
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.36
|
|
4
4
|
Summary: Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)
|
|
5
5
|
Author-email: cbrightly <chris.brightly@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-aidot-cameras"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.36"
|
|
8
8
|
description = "Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -584,6 +584,7 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
584
584
|
self._streaming_active: bool = False
|
|
585
585
|
self._stream_session: Optional[Any] = None
|
|
586
586
|
self._stream_task: Optional["asyncio.Task[None]"] = None
|
|
587
|
+
self._stream_mqtt_drain: Optional["asyncio.Future"] = None
|
|
587
588
|
self._last_frame_time: float = 0.0
|
|
588
589
|
self._keepalive_rtsp_url: Optional[str] = None # local serve URL (go2rtc pulls)
|
|
589
590
|
self._go2rtc_url: Optional[str] = None # go2rtc API base (prefer-go2rtc)
|
|
@@ -1981,6 +1982,16 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
1981
1982
|
await task
|
|
1982
1983
|
except (asyncio.CancelledError, Exception):
|
|
1983
1984
|
_LOGGER.debug("camera %s: swallowed exception", 'async_stop_streaming', exc_info=True)
|
|
1985
|
+
# Reap a persistent-MQTT stream drain that no session stopped (e.g. an
|
|
1986
|
+
# open cancelled mid-handshake): cancelling it runs its finally, which
|
|
1987
|
+
# removes the handler from the shared persistent connection.
|
|
1988
|
+
drain, self._stream_mqtt_drain = getattr(self, "_stream_mqtt_drain", None), None
|
|
1989
|
+
if drain is not None and not drain.done():
|
|
1990
|
+
drain.cancel()
|
|
1991
|
+
try:
|
|
1992
|
+
await drain
|
|
1993
|
+
except (asyncio.CancelledError, Exception):
|
|
1994
|
+
_LOGGER.debug("camera %s: swallowed exception", 'async_stop_streaming', exc_info=True)
|
|
1984
1995
|
|
|
1985
1996
|
async def async_start_motion_polling(
|
|
1986
1997
|
self, callback: Callable, interval: float = 30.0, lookback_s: int = 600,
|
|
@@ -2071,6 +2082,7 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
2071
2082
|
sdes_fast_liveplay: Optional[bool] = None,
|
|
2072
2083
|
sdes_skip_turn: Optional[bool] = None,
|
|
2073
2084
|
sdes_adaptive: Optional[bool] = None,
|
|
2085
|
+
sdes_audio_gain_db: Optional[float] = None,
|
|
2074
2086
|
) -> None:
|
|
2075
2087
|
"""Start a persistent stream that keeps the camera session alive.
|
|
2076
2088
|
|
|
@@ -2113,6 +2125,8 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
2113
2125
|
self._fast_connect_opt = fast_connect
|
|
2114
2126
|
if sdes_audio is not None:
|
|
2115
2127
|
self._sdes_audio_opt = sdes_audio
|
|
2128
|
+
if sdes_audio_gain_db is not None:
|
|
2129
|
+
self._sdes_audio_gain_opt = sdes_audio_gain_db
|
|
2116
2130
|
if live_stream_param is not None:
|
|
2117
2131
|
self._live_stream_param_opt = live_stream_param
|
|
2118
2132
|
if serve_relay is not None:
|
|
@@ -2734,6 +2748,19 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
2734
2748
|
return os.environ.get("AIDOT_SDES_SERVE_AUDIO", "").strip().lower() not in (
|
|
2735
2749
|
"0", "false", "no", "off")
|
|
2736
2750
|
|
|
2751
|
+
def _resolve_sdes_audio_gain_db(self) -> float:
|
|
2752
|
+
"""Gain (dB) applied to the served SDES audio (the camera mic runs hot).
|
|
2753
|
+
|
|
2754
|
+
Per-camera ``sdes_audio_gain_db`` (via ``start_keepalive``) wins; else the
|
|
2755
|
+
``AIDOT_SDES_AUDIO_GAIN_DB`` env; else ``-8``. A bad value falls back to
|
|
2756
|
+
the default rather than raising."""
|
|
2757
|
+
opt = getattr(self, "_sdes_audio_gain_opt", None)
|
|
2758
|
+
src = opt if opt is not None else os.environ.get("AIDOT_SDES_AUDIO_GAIN_DB", "-8")
|
|
2759
|
+
try:
|
|
2760
|
+
return float(src)
|
|
2761
|
+
except (ValueError, TypeError):
|
|
2762
|
+
return -8.0
|
|
2763
|
+
|
|
2737
2764
|
def _resolve_sdes_skip_turn(self) -> bool:
|
|
2738
2765
|
"""EXPERIMENTAL (opt-in, default off): skip the blocking SDES TURN relay
|
|
2739
2766
|
pre-allocation, for cameras reachable LAN-direct.
|
|
@@ -4227,6 +4254,13 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
4227
4254
|
_pm_stream.remove_handler(_on_mqtt_message)
|
|
4228
4255
|
|
|
4229
4256
|
mqtt_fut = asyncio.ensure_future(_pm_stream_drain())
|
|
4257
|
+
# Track the drain so teardown can reap it even if this open is
|
|
4258
|
+
# cancelled before a WebRTCSession takes ownership (the session
|
|
4259
|
+
# normally stops it via the outgoing_q sentinel). Without this an
|
|
4260
|
+
# open cancelled mid-handshake leaves the drain blocked on
|
|
4261
|
+
# outgoing_q.get forever and its handler registered on the shared
|
|
4262
|
+
# persistent connection.
|
|
4263
|
+
self._stream_mqtt_drain = mqtt_fut
|
|
4230
4264
|
_on_mqtt_ready({"connected": True, "rc": 0, "rc_str": "persistent"})
|
|
4231
4265
|
else:
|
|
4232
4266
|
mqtt_fut = loop.run_in_executor(
|
|
@@ -10052,18 +10086,13 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
10052
10086
|
if out_dir:
|
|
10053
10087
|
os.makedirs(out_dir, exist_ok=True)
|
|
10054
10088
|
# Build the ffmpeg command (single source of truth: _build_sdes_serve_cmd).
|
|
10055
|
-
_sdes_audio = self._resolve_sdes_serve_audio()
|
|
10056
|
-
try:
|
|
10057
|
-
_sdes_gain_db = float(os.environ.get("AIDOT_SDES_AUDIO_GAIN_DB", "-8"))
|
|
10058
|
-
except (ValueError, TypeError):
|
|
10059
|
-
_sdes_gain_db = -8.0
|
|
10060
10089
|
cmd = _build_sdes_serve_cmd(
|
|
10061
10090
|
sdp_path=sdp_path,
|
|
10062
10091
|
rtsp_push_url=rtsp_push_url,
|
|
10063
10092
|
output_path=output_path,
|
|
10064
10093
|
max_seconds=max_seconds,
|
|
10065
|
-
sdes_audio=
|
|
10066
|
-
audio_gain_db=
|
|
10094
|
+
sdes_audio=self._resolve_sdes_serve_audio(),
|
|
10095
|
+
audio_gain_db=self._resolve_sdes_audio_gain_db(),
|
|
10067
10096
|
)
|
|
10068
10097
|
# --- H.265 fix: narrow the ffmpeg SDP to the camera's actual codec ----
|
|
10069
10098
|
# The camera streams H.264 (pt=96) OR H.265 (pt=97), varying per session.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-aidot-cameras
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.36
|
|
4
4
|
Summary: Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)
|
|
5
5
|
Author-email: cbrightly <chris.brightly@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -48,6 +48,28 @@ def test_kwarg_option_wins_over_env(monkeypatch):
|
|
|
48
48
|
assert cam2._resolve_sdes_serve_audio() is True
|
|
49
49
|
|
|
50
50
|
|
|
51
|
+
def test_gain_default(monkeypatch):
|
|
52
|
+
monkeypatch.delenv("AIDOT_SDES_AUDIO_GAIN_DB", raising=False)
|
|
53
|
+
assert _cam()._resolve_sdes_audio_gain_db() == -8.0
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_gain_env(monkeypatch):
|
|
57
|
+
monkeypatch.setenv("AIDOT_SDES_AUDIO_GAIN_DB", "-3.5")
|
|
58
|
+
assert _cam()._resolve_sdes_audio_gain_db() == -3.5
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_gain_opt_wins(monkeypatch):
|
|
62
|
+
monkeypatch.setenv("AIDOT_SDES_AUDIO_GAIN_DB", "-3")
|
|
63
|
+
cam = _cam()
|
|
64
|
+
cam._sdes_audio_gain_opt = 2.0
|
|
65
|
+
assert cam._resolve_sdes_audio_gain_db() == 2.0
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_gain_bad_value_falls_back(monkeypatch):
|
|
69
|
+
monkeypatch.setenv("AIDOT_SDES_AUDIO_GAIN_DB", "loud")
|
|
70
|
+
assert _cam()._resolve_sdes_audio_gain_db() == -8.0
|
|
71
|
+
|
|
72
|
+
|
|
51
73
|
if __name__ == "__main__":
|
|
52
74
|
import traceback
|
|
53
75
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Unit test: async_stop_streaming reaps an orphaned persistent-MQTT drain.
|
|
2
|
+
|
|
3
|
+
If a stream open is cancelled before a WebRTCSession takes ownership of the
|
|
4
|
+
drain task, the drain would otherwise block forever on outgoing_q.get with its
|
|
5
|
+
handler still registered. async_stop_streaming must cancel it (its finally then
|
|
6
|
+
removes the handler). No camera needed.
|
|
7
|
+
"""
|
|
8
|
+
import asyncio
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "src"))
|
|
13
|
+
|
|
14
|
+
import aidot.camera.client as cc
|
|
15
|
+
|
|
16
|
+
_CAM = next(v for v in vars(cc).values()
|
|
17
|
+
if isinstance(v, type) and "async_stop_streaming" in v.__dict__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _bare_client():
|
|
21
|
+
c = _CAM.__new__(_CAM)
|
|
22
|
+
c._streaming_active = True
|
|
23
|
+
c._serve_ready = asyncio.Event()
|
|
24
|
+
c._go2rtc_task = None
|
|
25
|
+
c._stream_session = None
|
|
26
|
+
c._stream_task = None
|
|
27
|
+
c._stream_mqtt_drain = None
|
|
28
|
+
|
|
29
|
+
async def _noop_deregister():
|
|
30
|
+
return None
|
|
31
|
+
c._deregister_go2rtc = _noop_deregister
|
|
32
|
+
return c
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_orphaned_drain_is_cancelled():
|
|
36
|
+
async def _run():
|
|
37
|
+
c = _bare_client()
|
|
38
|
+
handler_removed = {"v": False}
|
|
39
|
+
|
|
40
|
+
async def _drain():
|
|
41
|
+
try:
|
|
42
|
+
await asyncio.Event().wait() # blocks forever, like outgoing_q.get
|
|
43
|
+
finally:
|
|
44
|
+
handler_removed["v"] = True # the real finally calls remove_handler
|
|
45
|
+
c._stream_mqtt_drain = asyncio.ensure_future(_drain())
|
|
46
|
+
await asyncio.sleep(0) # let the drain start blocking
|
|
47
|
+
|
|
48
|
+
await c.async_stop_streaming()
|
|
49
|
+
|
|
50
|
+
assert c._stream_mqtt_drain is None # cleared
|
|
51
|
+
assert handler_removed["v"] is True # drain's finally ran (handler removed)
|
|
52
|
+
asyncio.run(_run())
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_no_drain_is_safe():
|
|
56
|
+
async def _run():
|
|
57
|
+
c = _bare_client() # _stream_mqtt_drain is None
|
|
58
|
+
await c.async_stop_streaming() # must not raise
|
|
59
|
+
assert c._streaming_active is False
|
|
60
|
+
asyncio.run(_run())
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
if __name__ == "__main__":
|
|
64
|
+
import traceback
|
|
65
|
+
_fail = 0
|
|
66
|
+
for _k, _v in sorted(globals().items()):
|
|
67
|
+
if _k.startswith("test_"):
|
|
68
|
+
try:
|
|
69
|
+
_v()
|
|
70
|
+
print(f"PASS {_k}")
|
|
71
|
+
except Exception:
|
|
72
|
+
_fail += 1
|
|
73
|
+
print(f"FAIL {_k}")
|
|
74
|
+
traceback.print_exc()
|
|
75
|
+
raise SystemExit(1 if _fail else 0)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/models/device_client_model.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/models/device_model.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/src/aidot/models/discover_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_device_login_guard.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_highport_nomination.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_no_undefined_names.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_post_merge_hardening.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.7.34 → python_aidot_cameras-0.7.36}/tests/test_sdes_fast_liveplay.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|